首页 > 代码库 > [BZOJ 3514]Codechef MARCH14 GERALD07加强版

[BZOJ 3514]Codechef MARCH14 GERALD07加强版

这题的做法很巧妙,我却写的很作死……

今天算是狠狠的又补了一边 link-cut-tree ,完了又是发现自己很 SX 

考虑已经有 i 条边构成的图,现在要加入第 i+1 跳边

那么有两种情况:1.要么成环 2.要么不成环 (废话)

我们认为成环的边是没有贡献的,不成环的边是有贡献的

答案就是统计 l..r 条边中有贡献的边一共有几条,然后用 n 减一下

我们再次定义第 i 条边加入后构成的环中最早被加入的边是 ntr[i] ,然后从第一条边起,每次在加入第 i 条边后,把第 ntr[i] 条边删除(233…)

此时图始终呈一个生成森林

那么 l..r 条边中有贡献的边的条数就是 l..r 条边中 ntr[i]<l 的边数

因为 ntr[i]>=l 的说明这条边在加入后与 l..i 中的某条边构成了环,显然这是一条毫无贡献的边

ntr 数组可以用 link-cut-tree 来解决,每次在 u 和 v 间连一条权为 w 的边等价于把 u 和 v 连向一个权值为 w 的点,我们就解决了化边权为点权的问题

至于后面那个主席树就可以了……

这真是一道可怕的数据结构题

 

  1 #include <cstdio>  2 const int inf=0x7FFFFFFF;  3 const int sizeOfPoint=200002;  4   5 int n, m, k, type;  6 int u[sizeOfPoint], v[sizeOfPoint];  7 int time[sizeOfPoint<<1], ntr[sizeOfPoint];  8 inline int getint();  9 inline void putint(int); 10 template<class type> inline void swap(type & a, type & b) {type t=a; a=b; b=t;} 11  12 struct node 13 { 14     int id; 15     node * min; 16     bool rev; 17     node * f, * c[2]; 18     inline node():id(0), rev(0) {min=this; f=c[0]=c[1]=this;} 19     inline void maintain() {min=this; if (time[c[0]->min->id]<time[min->id]) min=c[0]->min; if (time[c[1]->min->id]<time[min->id]) min=c[1]->min;} 20     inline void pushdown() {if (rev) swap(c[0], c[1]), c[0]->rev^=1, c[1]->rev^=1, rev=0;} 21 }; 22 node * null=new node(); 23 node memoryOfLct[sizeOfPoint<<1], * portOfLct=memoryOfLct; 24 node * t[sizeOfPoint<<1]; 25 inline node * newnode(int _id) {node * ret=portOfLct++; ret->id=_id; ret->min=ret; ret->rev=0; ret->f=ret->c[0]=ret->c[1]=null; return ret;} 26 inline void rotate(node * x, int d) {node * y=x->f, * z=y->f; (y->c[d]=x->c[d^1])->f=y; (x->c[d^1]=y)->f=x; y->maintain(); if (z->c[0]==y) z->c[0]=x; if (z->c[1]==y) z->c[1]=x; x->f=z;} 27 inline void splay(node * x) 28 { 29     node * y, * z; bool d, dd; 30     x->pushdown(); 31     while ((y=x->f)!=null && (y->c[0]==x || y->c[1]==x)) 32         if ((z=y->f)!=null && (z->c[0]==y || z->c[1]==y)) 33         { 34             z->pushdown(), y->pushdown(), x->pushdown(); 35             d=y->c[1]==x, dd=z->c[1]==y; 36             if (d==dd) rotate(y, dd), rotate(x, d); 37             else rotate(x, d), rotate(x, dd); 38         } 39         else 40         { 41             y->pushdown(), x->pushdown(); 42             d=y->c[1]==x; 43             rotate(x, d); 44         } 45     x->maintain(); 46 } 47 inline node * access(node * x) {node * y; for (y=null;x!=null;x=x->f) splay(x), x->c[1]=y, (y=x)->maintain(); return y;} 48 inline void evert(node * x) {access(x)->rev^=1;} 49 inline node * find(node * x) {for ( ;x->f!=null;x=x->f); return x;} 50 inline void link(node * x, node * y) {evert(x); splay(x); x->f=y;} 51 inline void cut(node * x, node * y) {evert(x); access(y); splay(y); y->c[0]=y->c[0]->f=null;} 52 inline bool check(node * x, node * y) {return find(x)==find(y);} 53 inline node * query(node * x, node * y) {evert(x); access(y); splay(y); return y->min;} 54  55 struct seg {int cnt; seg * l, * r; inline seg():cnt(0) {l=r=this;}}; 56 seg * nul=new seg(); 57 seg memoryOfSeg[sizeOfPoint<<6], * portOfSeg=memoryOfSeg; 58 seg * T[sizeOfPoint]; 59 inline seg * newseg(seg * t=nul) {seg * newt=portOfSeg++; if (t!=nul) newt->cnt=t->cnt, newt->l=t->l, newt->r=t->r; else newt->cnt=0, newt->l=nul, newt->r=nul; return newt;} 60 seg * insert(seg * , int, int, int); 61  62 inline void prepare(); 63 inline void build(); 64 inline int query(int, int); 65  66 int main() 67 { 68     int lastans=0; 69     int l, r; 70  71     n=getint(); m=getint(); k=getint(); type=getint(); 72     for (int i=1;i<=m;i++) u[i]=getint(), v[i]=getint(); 73     prepare(); 74     build(); 75  76  77     for (int i=1;i<=k;i++) 78     { 79         l=getint(), r=getint(); 80         if (type) l^=lastans, r^=lastans; 81         putint(lastans=query(l, r)); 82     } 83  84     return 0; 85 } 86 inline int getint() 87 { 88     register int num=0; 89     register char ch; 90     do ch=getchar(); while (ch<0 || ch>9); 91     do num=num*10+ch-0, ch=getchar(); while (ch>=0 && ch<=9); 92     return num; 93 } 94 inline void putint(int num) 95 { 96     char stack[10]; 97     register int top=0; 98     if (num==0) stack[top=1]=0; 99     for ( ;num;num/=10) stack[++top]=num%10+0;100     for ( ;top;top--) putchar(stack[top]);101     putchar(\n);102 }103 seg * insert(seg * t, int l, int r, int k)104 {105     seg * newt=newseg(t);106     newt->cnt++;107     if (l==r) return newt;108     int m=(l+r)>>1;109     if (k<=m) newt->l=insert(newt->l, l, m, k);110     else newt->r=insert(newt->r, m+1, r, k);111     return newt;112 }113 inline void prepare()114 {115     for (int i=1;i<=n;i++) t[i]=newnode(i);116     for (int i=0;i<=n;i++) time[i]=inf;117     for (int i=1, j=n+1;i<=m;i++, j++)118     {119         if (u[i]==v[i]) {ntr[i]=i; continue;}120         if (check(t[u[i]], t[v[i]]))121         {122             node * c=query(t[u[i]], t[v[i]]);123             ntr[i]=time[c->id];124             cut(t[u[i]], c); cut(t[v[i]], c);125         }126         t[j]=newnode(j); time[j]=i;127         link(t[u[i]], t[j]); link(t[v[i]], t[j]);128     }129 }130 inline void build()131 {132     T[0]=nul;133     for (int i=1;i<=m;i++)134         T[i]=insert(T[i-1], 0, m, ntr[i]);135 }136 inline int query(int x, int y)137 {138     seg * i=T[x-1], * j=T[y];139     int ret=0;140     int left=0, right=m, mid;141     for ( ;j!=nul; )142     {143         mid=(left+right)>>1;144         if (x>mid)145         {146             ret+=j->l->cnt-i->l->cnt;147             i=i->r, j=j->r;148             left=mid+1;149         }150         else151         {152             i=i->l, j=j->l;153             right=mid;154         }155     }156     return n-ret;157 }
本傻莫名 T 出翔系列

 

[BZOJ 3514]Codechef MARCH14 GERALD07加强版