这题的做法很巧妙,我却写的很作死……
今天算是狠狠的又补了一边 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(' '); 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 else 151 { 152 i=i->l, j=j->l; 153 right=mid; 154 } 155 } 156 return n-ret; 157 }