解题: SDOI 2011 染色

题面

强行把序列问题通过树剖套在树上。。。算了算是回顾了一下树剖的思想=。=

每次树上跳的时候注意跳的同时维护当前拼出来的左右两条链的靠上的端点,然后拼起来的时候讨论一下拼接点,最后一下左右两边的端点都要考虑

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 using namespace std;
  5 const int N=100005;
  6 struct a
  7 {
  8     int cnt;
  9     int lc,rc;
 10 };
 11 int num[N],nmb[N],val[4*N],lcol[4*N],rcol[4*N],laz[4*N];
 12 int siz[N],dep[N],anc[N],imp[N],top[N],dfn[N];
 13 int p[N],noww[2*N],goal[2*N];
 14 int n,m,t1,t2,t3,cnt,tot;
 15 char rd[2];
 16 void link(int f,int t)
 17 {
 18     noww[++cnt]=p[f];
 19     goal[cnt]=t,p[f]=cnt;
 20 }
 21 void DFS(int nde,int fth,int dth)
 22 {
 23     int tmp=0;
 24     siz[nde]=1,anc[nde]=fth,dep[nde]=dth;
 25     for(int i=p[nde];i;i=noww[i])
 26         if(goal[i]!=fth)
 27         {
 28             DFS(goal[i],nde,dth+1);
 29             siz[nde]+=siz[goal[i]];
 30             if(siz[goal[i]]>tmp)
 31                 tmp=siz[goal[i]],imp[nde]=goal[i];
 32         }
 33 }
 34 void MARK(int nde,int tpp)
 35 {
 36     dfn[nde]=++tot,nmb[tot]=num[nde],top[nde]=tpp;
 37     if(imp[nde])
 38     {
 39         MARK(imp[nde],tpp);
 40         for(int i=p[nde];i;i=noww[i])
 41             if(goal[i]!=anc[nde]&&goal[i]!=imp[nde])
 42                 MARK(goal[i],goal[i]);
 43     }
 44 }
 45 void pushup(int nde)
 46 {
 47     int ls=2*nde,rs=2*nde+1;
 48     lcol[nde]=lcol[ls],rcol[nde]=rcol[rs];
 49     val[nde]=val[ls]+val[rs]-(rcol[ls]==lcol[rs]);
 50 }
 51 void create(int nde,int l,int r)
 52 {
 53     if(l==r)
 54         val[nde]=1,lcol[nde]=rcol[nde]=nmb[l];
 55     else
 56     {
 57         int mid=(l+r)/2,ls=2*nde,rs=2*nde+1;
 58         create(ls,l,mid),create(rs,mid+1,r);
 59         pushup(nde);
 60     }
 61 }
 62 void release(int nde,int l,int r)
 63 {
 64     if(laz[nde])
 65     {
 66         int ls=2*nde,rs=2*nde+1;
 67         laz[ls]=lcol[ls]=rcol[ls]=laz[nde];
 68         laz[rs]=lcol[rs]=rcol[rs]=laz[nde];
 69         val[ls]=val[rs]=1; laz[nde]=0;
 70     }
 71 }
 72 void change(int nde,int l,int r,int nl,int nr,int task)
 73 {
 74     if(l>nr||r<nl)
 75         return ;
 76     else if(l>=nl&&r<=nr)
 77         val[nde]=1,lcol[nde]=rcol[nde]=laz[nde]=task;
 78     else
 79     {
 80         int mid=(l+r)/2,ls=2*nde,rs=2*nde+1; release(nde,l,r);
 81         change(ls,l,mid,nl,nr,task),change(rs,mid+1,r,nl,nr,task);
 82         pushup(nde);
 83     }    
 84 }
 85 a query(int nde,int l,int r,int nl,int nr)
 86 {
 87     if(l>=nl&&r<=nr)
 88         return (a){val[nde],lcol[nde],rcol[nde]};
 89     else
 90     {
 91         int mid=(l+r)/2,ls=2*nde,rs=2*nde+1; release(nde,l,r); 
 92         if(nr<=mid) return query(ls,l,mid,nl,nr);
 93         if(nl>mid) return query(rs,mid+1,r,nl,nr);
 94         a r1=query(ls,l,mid,nl,nr),r2=query(rs,mid+1,r,nl,nr),ret;
 95         ret.lc=r1.lc,ret.rc=r2.rc,ret.cnt=r1.cnt+r2.cnt-(r1.rc==r2.lc);
 96         return ret;
 97     }    
 98 }
 99 void path_change(int x,int y,int v)
100 {
101     while(top[x]!=top[y])
102     {
103         if(dep[top[x]]<dep[top[y]]) swap(x,y);
104         change(1,1,n,dfn[top[x]],dfn[x],v); x=anc[top[x]];
105     }
106     if(dep[x]>dep[y]) swap(x,y);
107     change(1,1,n,dfn[x],dfn[y],v); return ;
108 }
109 int path_query(int x,int y)
110 {
111     int rt=0,ll=-1,rr=-1;
112     while(top[x]!=top[y])
113     {
114         if(dep[top[x]]<dep[top[y]]) swap(x,y),swap(ll,rr);
115         a ret=query(1,1,n,dfn[top[x]],dfn[x]); x=anc[top[x]];
116         rt+=ret.cnt-(ll==ret.rc); ll=ret.lc;
117     }
118     if(dep[x]>dep[y]) swap(x,y),swap(ll,rr);
119     a ret=query(1,1,n,dfn[x],dfn[y]); rt+=ret.cnt-(ll==ret.lc)-(rr==ret.rc); 
120     return rt;
121 }
122 int main ()
123 {
124     scanf("%d%d",&n,&m);
125     for(int i=1;i<=n;i++)
126         scanf("%d",&num[i]);
127     for(int i=1;i<n;i++)    
128         scanf("%d%d",&t1,&t2),link(t1,t2),link(t2,t1);
129     DFS(1,0,1); MARK(1,1); create(1,1,n);
130     while(m--)
131     {
132         scanf("%s",rd);
133         if(rd[0]=='C')
134             scanf("%d%d%d",&t1,&t2,&t3),path_change(t1,t2,t3);
135         else 
136             scanf("%d%d",&t1,&t2),printf("%d\n",path_query(t1,t2));
137     }
138     return 0;
139 }
View Code

 

转载于:https://www.cnblogs.com/ydnhaha/p/9743416.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
大学生参加学科竞赛有着诸多好处,不仅有助于个人综合素质的提升,还能为未来职业发展奠定良好基础。以下是一些分析: 首先,学科竞赛是提高专业知识和技能水平的有效途径。通过参与竞赛,学生不仅能够深入学习相关专业知识,还能够接触到最新的科研成果和技术发展趋势。这有助于拓展学生的学科视野,使其对专业领域有更深刻的理解。在竞赛过程中,学生通常需要解决实际问题,这锻炼了他们独立思考和解决问题的能力。 其次,学科竞赛培养了学生的团队合作精神。许多竞赛项目需要团队协作来完成,这促使学生学会有效地与他人合作、协调分工。在团队合作中,学生们能够学到如何有效沟通、共同制定目标和分工合作,这对于日后进入职场具有重要意义。 此外,学科竞赛是提高学生综合能力的一种途径。竞赛项目通常会涉及到理论知识、实际操作和创新思维等多个方面,要求参赛者具备全面的素质。在竞赛过程中,学生不仅需要展现自己的专业知识,还需要具备创新意识和解决问题的能力。这种全面的综合能力培养对于未来从事各类职业都具有积极作用。 此外,学科竞赛可以为学生提供展示自我、树立信心的机会。通过比赛的舞台,学生有机会展现自己在专业领域的优势,得到他人的认可和赞誉。这对于培养学生的自信心和自我价值感非常重要,有助于他们更加积极主动地投入学习和未来的职业生涯。 最后,学科竞赛对于个人职业发展具有积极的助推作用。在竞赛中脱颖而出的学生通常能够引起企业、研究机构等用人单位的关注。获得竞赛奖项不仅可以作为个人履历的亮点,还可以为进入理想的工作岗位提供有力的支持。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值