您的位置:首页 > 其它

[LCT 主席树] BZOJ 3514 Codechef MARCH14 GERALD07加强版

2017-01-31 18:40 363 查看
N个点M条边的无向图,询问保留图中编号在[l,r]的边的时候图中的联通块个数。

先预处理

按时间做一通最大生成树

每次加边 i 替换树上的最小边 记这条边为 a[i]

特殊的 如果本来不连通 a[i]=0 如果是自环 a[i]=i

对于每个询问[l,r],统计区间[l,r]中有多少个数小于l,用n去减即可得答案

为什么呢 因为替换了一条小于l的边 那么相当于只保留[l,r]的边时 连接了两个连通块

今天换了一种姿势码LCT 代码短短哒 总行数只有100

#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<stack>
using namespace std;

inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; }
return *p1++;
}

inline void read(int &x){
char c=nc(),b=1;
for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}

const int N=400005;

int n,m;
int us
,vs
,ws
;
inline int Min(int x,int y) { return ws[x]<ws[y]?x:y; }

struct node{
node *f,*ch[2];
int idx,v; bool rev;
bool isr() { return !f || (f->ch[0]!=this && f->ch[1]!=this); }
bool dir() { return f->ch[1]==this; }
void setc(node *c,int d) { ch[d]=c; if (c) c->f=this; }
void push() {
if (rev) { swap(ch[0],ch[1]); if(ch[0])ch[0]->rev^=1; if(ch[1])ch[1]->rev^=1; rev=0;}
}
void upd() {
v=idx; if(ch[0])v=Min(v,ch[0]->v); if(ch[1])v=Min(v,ch[1]->v);
}
}pool
,*cur;
inline void rot(node *x){
node *p=x->f; bool d=x->dir();
if (!p->isr()) p->f->setc(x,p->dir()); else x->f=p->f;
p->setc(x->ch[d^1],d); x->setc(p,d^1); p->upd();
}
stack<node*> sta;
inline void splay(node *x){
node *q=x; for (;!q->isr();q=q->f) sta.push(q); sta.push(q);
while (!sta.empty()) sta.top()->push(),sta.pop();
while (!x->isr())
if (x->f->isr()) rot(x);
else if (x->dir()==x->f->dir()) rot(x->f),rot(x);
else rot(x),rot(x);
x->upd();
}
void expose(node *x){
for (node *q=NULL;x;q=x,x=x->f) splay(x),x->ch[1]=q,x->upd();
}
void exert(node *x){ expose(x); splay(x); x->rev^=1; }
void link(node *x,node *y) { exert(y); y->f=x; }
void cut(node *x,node *y) { exert(x); expose(y); splay(y); y->ch[0]=x->f=NULL; y->upd(); }
node *frt(node *x){ expose(x),splay(x); for (;x->push(),x->ch[0];x=x->ch[0]); return x; }
int query(node *x,node *y){ exert(x); expose(y); splay(y); return y->v; }

int root
,ls[N*30],rs[N*30],s[N*30];
int ncnt;

inline void add(int &x,int y,int l,int r,int t){
x=++ncnt; int mid=(l+r)>>1;
s[x]=s[y]+1; if (l==r) return;
if (t<=mid)
add(ls[x],ls[y],l,mid,t),rs[x]=rs[y];
else
add(rs[x],rs[y],mid+1,r,t),ls[x]=ls[y];
}
inline int query(int x,int l,int r,int ql,int qr){
if (ql<=l && r<=qr) return s[x];
int ret=0,mid=(l+r)>>1;
if (ql<=mid) ret+=query(ls[x],l,mid,ql,qr);
if (qr>mid) ret+=query(rs[x],mid+1,r,ql,qr);
return ret;
}

int a
;

int main(){
int Q,lastans=0,t,l,r;
freopen("t.in","r",stdin);
freopen("t.out","w",stdout);
read(n); read(m); read(Q); read(t);
for (int i=1;i<=m;i++) read(us[i]),read(vs[i]),ws[i]=i;
for (int i=m+1;i<=m+n;i++) ws[i]=1<<30;
for (int i=1;i<=n+m;i++) pool[i].idx=pool[i].v=i;
for (int i=1;i<=m;i++){
if (us[i]==vs[i]) { a[i]=i; continue; }
if (frt(pool+m+us[i])==frt(pool+m+vs[i])){
int p=query(pool+m+us[i],pool+m+vs[i]); a[i]=p;
cut(pool+p,pool+m+us[p]),cut(pool+p,pool+m+vs[p]);
link(pool+i,pool+m+us[i]),link(pool+i,pool+m+vs[i]);
}else
link(pool+i,pool+m+us[i]),link(pool+i,pool+m+vs[i]),a[i]=0;
}
for (int i=1;i<=m;i++) add(root[i],root[i-1],0,m,a[i]);
while (Q--){
read(l); read(r); l^=lastans*t,r^=lastans*t;
int tem=query(root[r],0,m,0,l-1)-query(root[l-1],0,m,0,l-1);
printf("%d\n",lastans=n-tem);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: