CF 12D BALL 線段樹 && 樹狀數組

來源:互聯網
上載者:User

http://codeforces.com/problemset/problem/12/D

線段樹

View Code

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int inf = ~0u>>2;const int N = 500010;#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1int Max[N<<2];struct node{    int x,y,z;}in[N];int tot,n;int num[N];int max(int a,int b){    return a>b?a:b;}void pushup(int rt){    Max[rt]=max(Max[rt<<1],Max[rt<<1|1]);}void build(int l,int r,int rt){    Max[rt]=0;    if(l==r) return ;    int m=(l+r)>>1;    build(lson);    build(rson);}void update(int p,int val,int l,int r,int rt){    if(l==r){        if(val>Max[rt])            Max[rt]=val;        return ;    }    int m=(l+r)>>1;    if(p<=m) update(p,val,lson);    else update(p,val,rson);    pushup(rt);}int query(int L,int R,int l,int r,int rt){    if(L<=l&&r<=R)      return Max[rt];    int m=(l+r)>>1;    int ret=0;    if(L<=m) ret=max(ret,query(L,R,lson));    if(R>m) ret=max(ret,query(L,R,rson));    return ret;}void init(){    sort(num+1,num+n+1);    tot=unique(num+1,num+n+1)-num-1;    build(1,tot,1);    for(int i=1;i<=n;i++)        in[i].x=lower_bound(num+1,num+1+tot,in[i].x)-num;}inline int cmp(node a,node b){    return a.y>b.y;}int main(){    int i,j,k;    scanf("%d",&n);    for(i=1;i<=n;i++) {scanf("%d",&in[i].x);    num[i]=in[i].x;}    for(i=1;i<=n;i++) scanf("%d",&in[i].y);    for(i=1;i<=n;i++) scanf("%d",&in[i].z);    init();    sort(in+1,in+n+1,cmp);    int ans=0;    for(i=1;i<=n;i=j){        for(j=i;j<=n&&in[j].y==in[i].y;j++){            int z;            z=query(in[j].x+1,tot,1,tot,1);            if(z>in[j].z) ans++;        }        for(;i<=j-1;i++)            update(in[i].x,in[i].z,1,tot,1);    }    printf("%d\n",ans);    return 0;}/*31 3 52 4 63 5 7*/

 

樹狀數組

View Code

/*CF  12D樹狀數組好題給你n個整數三元組,對於某個三元組,判斷是否存在一個三元組的元素都大於這個三元組題目給三個數,必然有其道理可以把其中一個數離散化當做樹狀數組的下標,再按照另外某個數排序最後就只需利用樹狀數組數組處理好最後一個數就行了具體做法:比如對x離散化   對y降序排序   x當做樹狀數組的下標每次把y值相同的三元組一起拿出來處理因為前面加進樹狀數組的數的y值肯定比現在這個數的y值要大,這一個數就不必考慮瞭然後就是找前面加進樹狀數組的數中有沒有z座標 大於 當前枚舉的數的z座標,當然是在大於x的區間內這裡與樹狀數組的功能相反了,這裡樹狀數組是求前n項中的最大值,而題目要求下標在x->n間的最大值轉換一下就好了離散化前:1 3 5 7 9離散化後並不是1 2 3 4 5要倒過來:5 4 3 2 1那麼小於x的區間實際上就是大於x的區間*/#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int N = 500010;int c[N];int num[N];int n;struct node{    int x,y,z;}in[N];inline void Max(int &a,int b){    if(a<b) a=b;}void update(int x,int d){    for(;x<N;x+=x&-x)    Max(c[x],d);}int sum(int x){    int ans=0;    for(;x>0;x-=x&-x)    Max(ans,c[x]);    return ans;}void init(){     sort(num+1,num+n+1);     int tot=unique(num+1,num+n+1)-num-1;     for(int i=1;i<=n;i++)         in[i].x=tot-(lower_bound(num+1,num+1+tot,in[i].x)-num-1);     //把x的相對大小倒了過來  所以小於in[i].x實際表示大於in[i].x;,便於樹狀數組的sum操作}inline int cmp(node a,node b){    return a.y>b.y;}int main(){    int i,j,k;    scanf("%d",&n);    for(i=1;i<=n;i++) {scanf("%d",&in[i].x);    num[i]=in[i].x;}    for(i=1;i<=n;i++) scanf("%d",&in[i].y);    for(i=1;i<=n;i++) scanf("%d",&in[i].z);    init();    memset(c,0,sizeof(c));    sort(in+1,in+n+1,cmp);    int ans=0;    for(i=1;i<=n;i=j){        for(j=i;j<=n&&in[j].y==in[i].y;j++){            int z=sum(in[j].x-1);            if(z>in[j].z) ans++;        }        for(;i<=j-1;i++)            update(in[i].x,in[i].z);    }    printf("%d\n",ans);    return 0;}/*31 3 52 4 63 5 7*/

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.