[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         else

151         {

152             i=i->l, j=j->l;

153             right=mid;

154         }

155     }

156     return n-ret;

157 }
本傻莫名 T 出翔系列

 

你可能感兴趣的:(code)