zoukankan      html  css  js  c++  java
  • COGS 2479 偏序 题解

    【题意】

    给定一个有n个元素的序列,元素编号为1~n,每个元素有三个属性a,b,c,求序列中满足i<j且ai<aj且bi<bj且ci<cj的数对(i,j)的个数。

    对于30%的数据,n<=5000。

    对于100%的数据,1<=n<=50000(原题写错了哈哈),保证所有的ai、bi、ci分别组成三个1~n的排列。

    【解法】

    标题已经说了这是偏序,读完题,这就是个四维偏序模板题(位置一维,a,b,c剩下三维)。

    解法多多,我用的是CDQ树套树(树套树写的树状数组套替罪羊树,毕竟在我的印象里替罪羊树在随机数据下跑得飞快)。

    第一维已经有序,不用我们预处理,这样就可以按第一维(位置)分治,再把第二维(a)排序,剩下的第三维(b)和第四维(c)直接树套树就可以了(我用的是第三维树状数组,第四维平衡树)。

    当然写CDQ套CDQ+树状数组应该也可以,然而本鶸渣不会写……

    也可以写树套树套树……然而怎么写……

    贴个代码:

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 #define siz(x) ((x)?((x)->size):(0))
      5 #define lowbit(x) ((x)&(-(x)))
      6 using namespace std;
      7 const int maxn=50010;
      8 const double A=0.65;
      9 struct node{//Scapegoat Tree
     10     int data,size;
     11     node *lc,*rc,*prt;
     12     node(int d=0):data(d),size(1),lc(NULL),rc(NULL),prt(NULL){}
     13     inline void refresh(){size=siz(lc)+siz(rc)+1;}
     14 }*root[maxn];
     15 struct B{
     16     int id,a,b,c;
     17     bool operator<(const B &a)const{return this->a<a.a;}
     18 }a[maxn],b[maxn];
     19 void CDQ(int,int);
     20 void add(int,int);
     21 void del(int,int);
     22 int query(int,int);
     23 void insert(int);
     24 void erase(int);
     25 int rank(int);
     26 node *insert(node*);
     27 node *find(int);
     28 node *erase(node*);
     29 node *findmax(node*);
     30 void rebuild(node*);
     31 void zorder(node*);
     32 void removetree(node*);
     33 node *rebuild(int,int);
     34 int n,T,cnt,data[maxn];
     35 long long ans=0ll;
     36 int main(){
     37 #define MINE
     38 #ifdef MINE
     39     freopen("partial_order.in","r",stdin);
     40     freopen("partial_order.out","w",stdout);
     41 #endif
     42     scanf("%d",&n);
     43     for(int i=1;i<=n;i++)a[i].id=i;
     44     for(int i=1;i<=n;i++)scanf("%d",&a[i].a);
     45     for(int i=1;i<=n;i++)scanf("%d",&a[i].b);
     46     for(int i=1;i<=n;i++)scanf("%d",&a[i].c);
     47     CDQ(1,n);
     48     printf("%lld",ans);
     49 #ifndef MINE
     50     printf("
    -------------------------DONE-------------------------
    ");
     51     for(;;);
     52 #endif
     53     return 0;
     54 }
     55 void CDQ(int l,int r){
     56     if(l>=r)return;
     57     int mid=(l+r)>>1;
     58     CDQ(l,mid);
     59     CDQ(mid+1,r);
     60     int i=l,j=mid+1,k=l;
     61     while(i<=mid&&j<=r){
     62         if(a[i]<a[j])b[k++]=a[i++];
     63         else b[k++]=a[j++];
     64     }
     65     while(i<=mid)b[k++]=a[i++];
     66     while(j<=r)b[k++]=a[j++];
     67     for(int i=l;i<=r;i++){
     68         a[i]=b[i];
     69         if(a[i].id<=mid)add(a[i].b,a[i].c);
     70         else ans+=query(a[i].b,a[i].c);
     71     }
     72     for(int i=l;i<=r;i++)if(a[i].id<=mid)del(a[i].b,a[i].c);
     73 }
     74 void add(int x,int d){
     75     while(x<=n){
     76         T=x;
     77         insert(d);
     78         x+=lowbit(x);
     79     }
     80 }
     81 void del(int x,int d){
     82     while(x<=n){
     83         T=x;
     84         erase(d);
     85         x+=lowbit(x);
     86     }
     87 }
     88 int query(int x,int d){
     89     int ans=0;
     90     while(x){
     91         T=x;
     92         ans+=rank(d);
     93         x-=lowbit(x);
     94     }
     95     return ans;
     96 }
     97 void insert(int x){
     98     node *rt=insert(new node(x));
     99     if(rt)rebuild(rt);
    100 }
    101 void erase(int x){
    102     node *rt=erase(find(x));
    103     if(rt)rebuild(rt);
    104 }
    105 int rank(int x){
    106     node *rt=root[T];
    107     int ans=0;
    108     while(rt){
    109         if(x<=rt->data)rt=rt->lc;
    110         else{
    111             ans+=siz(rt->lc)+1;
    112             rt=rt->rc;
    113         }
    114     }
    115     return ans;
    116 }
    117 node *insert(node *x){
    118     if(!root[T]){
    119         root[T]=x;
    120         return NULL;
    121     }
    122     node *rt=root[T];
    123     for(;;){
    124         if(x->data<rt->data){
    125             if(rt->lc)rt=rt->lc;
    126             else{
    127                 rt->lc=x;
    128                 break;
    129             }
    130         }
    131         else{
    132             if(rt->rc)rt=rt->rc;
    133             else{
    134                 rt->rc=x;
    135                 break;
    136             }
    137         }
    138     }
    139     x->prt=rt;
    140     x=NULL;
    141     for(;rt;rt=rt->prt){
    142         rt->refresh();
    143         if(max(siz(rt->lc),siz(rt->rc))>A*rt->size)x=rt;
    144     }
    145     return x;
    146 }
    147 node *find(int x){
    148     node *rt=root[T];
    149     while(rt){
    150         if(x==rt->data)return rt;
    151         else if(x<rt->data)rt=rt->lc;
    152         else rt=rt->rc;
    153     }
    154     return NULL;
    155 }
    156 node *erase(node *x){
    157     if(x->lc&&x->rc){
    158         node *y=findmax(x->lc);
    159         x->data=y->data;
    160         return erase(y);
    161     }
    162     if(!x->lc&&!x->rc){
    163         if(x->prt){
    164             if(x==x->prt->lc)x->prt->lc=NULL;
    165             else x->prt->rc=NULL;
    166         }
    167         else root[T]=NULL;
    168     }
    169     else if(x->lc&&!x->rc){
    170         x->lc->prt=x->prt;
    171         if(x->prt){
    172             if(x==x->prt->lc)x->prt->lc=x->lc;
    173             else x->prt->rc=x->lc;
    174         }
    175         else root[T]=x->lc;
    176     }
    177     else if(!x->lc&&x->rc){
    178         x->rc->prt=x->prt;
    179         if(x->prt){
    180             if(x==x->prt->lc)x->prt->lc=x->rc;
    181             else x->prt->rc=x->rc;
    182         }
    183         else root[T]=x->rc;
    184     }
    185     node *rt=x->prt;
    186     delete x;
    187     x=NULL;
    188     for(;rt;rt=rt->prt){
    189         rt->refresh();
    190         if(max(siz(rt->lc),siz(rt->rc))>A*rt->size)x=rt;
    191     }
    192     return x;
    193 }
    194 node *findmax(node *x){
    195     while(x->rc)x=x->rc;
    196     return x;
    197 }
    198 void rebuild(node *rt){
    199     cnt=0;
    200     zorder(rt);
    201     node *x=rebuild(1,cnt);
    202     x->prt=rt->prt;
    203     if(rt->prt){
    204         if(rt==rt->prt->lc)rt->prt->lc=x;
    205         else rt->prt->rc=x;
    206     }
    207     else root[T]=x;
    208     removetree(rt);
    209 }
    210 void removetree(node *x){
    211     if(!x)return;
    212     removetree(x->lc);
    213     removetree(x->rc);
    214     delete x;
    215 }
    216 void zorder(node *x){
    217     if(!x)return;
    218     zorder(x->lc);
    219     data[++cnt]=x->data;
    220     zorder(x->rc);
    221 }
    222 node *rebuild(int l,int r){
    223     if(l>r)return NULL;
    224     int mid=(l+r)>>1;
    225     node *x=new node(data[mid]);
    226     x->lc=rebuild(l,mid-1);
    227     if(x->lc)x->lc->prt=x;
    228     x->rc=rebuild(mid+1,r);
    229     if(x->rc)x->rc->prt=x;
    230     x->refresh();
    231     return x;
    232 }
    View Code

    【后记】

    这个题是用CDQ+树状数组水掉三维偏序之后的脑洞的产物……貌似在报复社会……

    自己真是玩疯了……

    233333333
  • 相关阅读:
    CloudFlare防护下的破绽:寻找真实IP的几条途径
    用Log Parser Studio分析IIS日志
    Log Parser 2.2 + Log Parser Lizard GUI 分析IIS日志示例
    wordPress Development
    MyISAM 与 InnoDB 的区别
    ubuntu安装wiz笔记
    chown命令
    (转载)我们工作到底为了什么
    DS_Store 是什么文件
    Linux命令 ,在当前目录下查找一个,或者多个文件
  • 原文地址:https://www.cnblogs.com/hzoier/p/5939468.html
Copyright © 2011-2022 走看看