BZOJ 2243: [SDOI2011]染色(树链剖分)

很裸的一道树链剖分= =直接上代码

PS:调不了几次就过了真开心~~~

CODE:

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
#define maxn 100010
#define maxm 200010
struct edges{
 int to,next;
}edge[maxm];
int next[maxn],ednum;
int addedge(int from,int to){
 ednum++;
 edge[ednum*2]=(edges){to,next[from]};
 edge[ednum*2+1]=(edges){from,next[to]};
 next[from]=ednum*2;
 next[to]=ednum*2+1;
 return 0;
}
bool b[maxn];
int dep[maxn],sum[maxn],pos[maxn],color[maxn],add[maxn],fa[maxn],pre[maxn],ch[maxn];
int cnt;
int dfs(int u){
 dep[u]=dep[fa[u]]+1;
 b[u]=1;sum[u]=1;
 for (int i=next[u];i;i=edge[i].next)
  if (!b[edge[i].to]) {
   fa[edge[i].to]=u;
   dfs(edge[i].to);
   sum[u]+=sum[edge[i].to];
   ch[u]=sum[ch[u]]<sum[edge[i].to]?edge[i].to:ch[u];
  }
 return 0;
}
int heavy(int u,bool bo){
 b[u]=1;
 if (bo) pre[u]=u;
 else pre[u]=pre[fa[u]];
 add[pos[++cnt]=u]=cnt;
 if (ch[u]) heavy(ch[u],false);
 for (int i=next[u];i;i=edge[i].next)
  if (!b[edge[i].to]) heavy(edge[i].to,true);
 return 0;
}
struct bake{
 int l,r,sum;
};
bake operator +(const bake &x,const bake &y){
 bake ans;
 ans=(bake){x.l==-1?y.l:x.l,y.r==-1?x.r:y.r,x.sum+y.sum};
 if (x.r==y.l) ans.sum--;
 return ans;
}
struct node{
 int l,r;bake b;bool flag;
}t[maxn*8];
int set(int x,int col){
 t[x].b.l=t[x].b.r=col;t[x].b.sum=1;t[x].flag=1;
 return 0;
}
int build(int x,int l,int r){
 t[x].l=l;t[x].r=r;t[x].flag=0;
 if (l==r) {set(x,color[pos[l]]);return 0;}
 build(x<<1,l,(l+r)>>1);build((x<<1)+1,((l+r)>>1)+1,r);
 t[x].b=t[x<<1].b+t[(x<<1)+1].b;
 return 0;

int pushback(int x){
 if (t[x].flag){
  t[x].flag=0;
  set(x<<1,t[x].b.l);
  set((x<<1)+1,t[x].b.l);
 }
 return 0;
}
int cha(int x,int x1,int y1,int col){
 pushback(x);
 int l=t[x].l,r=t[x].r;
 if (y1<l||x1>r) return 0;
 if (l>=x1&&r<=y1) {set(x,col);return 0;}
 cha(x<<1,x1,y1,col);cha((x<<1)+1,x1,y1,col);
 t[x].b=t[x<<1].b+t[(x<<1)+1].b;
}
int change(int l,int r,int co){
 for (;;){
  if (pre[l]==pre[r]){
   if (dep[l]>dep[r]) swap(l,r) ;
   cha(1,add[l],add[r],co);
   return 0;
  }else {
   if (dep[pre[l]]<dep[pre[r]]) swap(l,r);
   cha(1,add[pre[l]],add[l],co);
   l=fa[pre[l]];
  }
 }
 return 0;
}
bake get(int x,int x1,int y1){
 pushback(x);
 int l=t[x].l,r=t[x].r;
 if (y1<l||x1>r) return (bake){-1,-1,0};
 if (l>=x1&&r<=y1) return t[x].b;
 return (get(x<<1,x1,y1)+get((x<<1)+1,x1,y1));
}
int query(int l,int r){
 bake la=(bake){-1,-1,0},ra=(bake){-1,-1,0};
 for (;;){
  if (pre[l]==pre[r]){
   if (dep[l]>dep[r]) {swap(l,r) ;swap(la,ra);}
   ra=get(1,add[l],add[r])+ra;
   int ans=ra.sum+la.sum;
   if (ra.l==la.l) ans--;
   return ans;
  }else {
   if (dep[pre[l]]<dep[pre[r]]) {swap(la,ra);swap(l,r);}
   la=get(1,add[pre[l]],add[l])+la;
   l=fa[pre[l]];
  }
 }
}
int main(){
 int n,m;
 scanf("%d%d",&n,&m);
 for (int i=1;i<=n;i++) scanf("%d",color+i);
 for (int i=1;i<n;i++) {
  int x,y;
  scanf("%d%d",&x,&y);
  addedge(x,y);
 }
 memset(b,0,sizeof(b));
 dfs(1);
 memset(b,0,sizeof(b));
 heavy(1,true);
 build(1,1,n);
 for (int i=1;i<=m;i++) {
  char s[2];int x,y,z;
  scanf("%s",s);
  if (s[0]=='C') {
   scanf("%d%d%d",&x,&y,&z);
   change(x,y,z);
  }else{
   scanf("%d%d",&x,&y);
   printf("%d\n",query(x,y));
  }
 }
 return 0;
}

posted @ 2014-06-29 15:12  New_Godess  阅读(126)  评论(0编辑  收藏  举报