BZOJ 2243 染色
Posted ziliuziliu
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ 2243 染色相关的知识,希望对你有一定的参考价值。
呀这个还有代码编辑器啊。。我今天才发现。
链剖水题。维护区间左端点和右端点的颜色。
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #define maxv 200500 #define maxe 200500 #define maxn 805000 using namespace std; int n,m,num[maxv],x,y,root=1,nume=0,tot=0,cnt=0,g[maxv]; int dis[maxv],top[maxv],fath[maxv],size[maxv],son[maxv],w[maxv],fw[maxv]; int ls[maxn],rs[maxn],lpos[maxn],rpos[maxn],lazy[maxn],sum[maxn]; int a,b,c; bool vis[maxv],fff[maxv]; char type[5]; struct edge { int v,nxt; }e[maxe]; void addedge(int u,int v) { e[++nume].v=v; e[nume].nxt=g[u]; g[u]=nume; } void dfs1(int x) { son[x]=0;size[x]=1; for (int i=g[x];i;i=e[i].nxt) { int v=e[i].v; if (v!=fath[x]) { fath[v]=x; dis[v]=dis[x]+1; dfs1(v); if (size[v]>size[son[x]]) son[x]=v; size[x]=size[x]+size[v]; } } } void dfs2(int x,int fa) { w[x]=++cnt;fw[cnt]=x;top[x]=fa; if (son[x]!=0) dfs2(son[x],fa); for (int i=g[x];i;i=e[i].nxt) { int v=e[i].v; if ((v!=fath[x]) && (v!=son[x])) dfs2(v,v); } } void build(int &now,int left,int right) { now=++tot;lpos[now]=0;rpos[now]=0;lazy[now]=-1; if (left==right) { int regis; regis=num[fw[left]]; lpos[now]=regis;rpos[now]=regis; sum[now]=1; return; } int mid=(left+right)>>1; build(ls[now],left,mid); build(rs[now],mid+1,right); lpos[now]=lpos[ls[now]];rpos[now]=rpos[rs[now]]; sum[now]=sum[ls[now]]+sum[rs[now]]; if (rpos[ls[now]]==lpos[rs[now]]) sum[now]=sum[now]-1; } void pushdown(int now,int left,int right) { if (lazy[now]!=-1) { lazy[ls[now]]=lazy[now];lazy[rs[now]]=lazy[now]; lpos[ls[now]]=lazy[now];lpos[rs[now]]=lazy[now]; rpos[ls[now]]=lazy[now];rpos[rs[now]]=lazy[now]; sum[ls[now]]=1;sum[rs[now]]=1; lazy[now]=-1; } } void modify(int now,int left,int right,int l,int r,int p) { pushdown(now,left,right); if ((left==l) && (right==r)) { lazy[now]=p;sum[now]=1; lpos[now]=p;rpos[now]=p; return; } int mid=(left+right)>>1; if (r<=mid) modify(ls[now],left,mid,l,r,p); else if (l>=mid+1) modify(rs[now],mid+1,right,l,r,p); else { modify(ls[now],left,mid,l,mid,p); modify(rs[now],mid+1,right,mid+1,r,p); } lpos[now]=lpos[ls[now]];rpos[now]=rpos[rs[now]]; sum[now]=sum[ls[now]]+sum[rs[now]]; if (rpos[ls[now]]==lpos[rs[now]]) sum[now]=sum[now]-1; } int ask(int now,int left,int right,int l,int r) { pushdown(now,left,right); if ((left==l) && (right==r)) return sum[now]; int mid=(left+right)>>1; if (r<=mid) return ask(ls[now],left,mid,l,r); else if (l>=mid+1) return ask(rs[now],mid+1,right,l,r); else { int regis=0; regis=ask(ls[now],left,mid,l,mid)+ask(rs[now],mid+1,right,mid+1,r); if (rpos[ls[now]]==lpos[rs[now]]) regis--; return regis; } } int find(int now,int left,int right,int p) { pushdown(now,left,right); if (left==p) return lpos[now]; int mid=(left+right)>>1; if (p<=mid) return find(ls[now],left,mid,p); else return find(rs[now],mid+1,right,p); } void work1() { scanf("%d%d%d",&a,&b,&c); int f1=top[a],f2=top[b]; while (f1!=f2) { if (dis[f1]<dis[f2]) {swap(f1,f2);swap(a,b);} modify(root,1,cnt,w[f1],w[a],c); a=fath[f1];f1=top[a]; } if (dis[a]>dis[b]) swap(a,b); modify(root,1,cnt,w[a],w[b],c); } void work2() { int ans=0; scanf("%d%d",&a,&b); int f1=top[a],f2=top[b]; while (f1!=f2) { if (dis[f1]<dis[f2]) {swap(f1,f2);swap(a,b);} ans=ans+ask(root,1,cnt,w[f1],w[a]); a=fath[f1]; if (find(root,1,cnt,w[a])==find(root,1,cnt,w[f1])) ans--; f1=top[a]; } if (dis[a]>dis[b]) swap(a,b); ans=ans+ask(root,1,cnt,w[a],w[b]); printf("%d\n",ans); } int main() { scanf("%d%d",&n,&m); for (int i=1;i<=n;i++) scanf("%d",&num[i]); for (int i=1;i<=n-1;i++) { scanf("%d%d",&x,&y); addedge(x,y); addedge(y,x); } dfs1(root); dfs2(root,root); build(root,1,cnt); for (int i=1;i<=m;i++) { scanf("%s",type); if (type[0]==‘C‘) work1(); else work2(); } return 0; }
以上是关于BZOJ 2243 染色的主要内容,如果未能解决你的问题,请参考以下文章
bzoj-2243 2243: [SDOI2011]染色(树链剖分)
bzoj2243: [SDOI2011]染色--线段树+树链剖分