zoukankan      html  css  js  c++  java
  • bzoj2243树链剖分+染色段数

    终于做了一道不是一眼出思路的代码题(⊙o⊙)

    之前没有接触过这种关于染色段数的题目(其实上课好像讲过),于是百度了一下(现在思维能力好弱)

    实际上每一段有用的信息就是总共有几段和两段各是什么颜色,在开线段树的时候记录一下就好了

    事实上我开了一个node,并且写了一个mix还是大大减小了代码量(对于我这种手残党来说同时大大减小了错误率)

    由于前几题做的都是树链剖分,并没有在这一方面出问题,然而线段树还是不熟练,刚写完的时候居然忘记down了(mdzz)

    对wa了N遍的总结:

    由于是树上两个点间的路径,既有向上的路也有向下的路,然而树剖下来的结果是按深度排的,所以在链上跑的时候会发现一段链的左右(l和r)有时候是相反的,在合并几条链的时候一定要注意(事实证明我这么多遍wa全是因为没有翻转链)

    对这一类问题的总结:

    对于每一段都考虑有用(会对周围产生影响)的信息,在染色段数中就是两端(因为可能和隔壁合并)

      1 //加了一大堆斜杠的是第一遍写之后补的
      2 #include <cstdio>
      3 #include <iostream>
      4 #define mid (l+r)/2
      5 using namespace std;
      6 int m=0,N=0,n,M,p,q,o;
      7 int to[200001],nex[200001],fir[100001],son[100001],bro[100001],co[100001];
      8 int size[100001],l[100001],pos[100001],fa[100001],h[100001],top[100001];
      9 struct node{int s,l,r;bool b;}t[500000],ans[2];
     10 inline void add(int x,int y){to[++m]=y;nex[m]=fir[x];fir[x]=m;}
     11 inline node mix(node x,node y){return (node){x.s+y.s-(x.r==y.l),x.l,y.r,0};}
     12 int build(int now,int fat)
     13 {
     14     size[now]=1;fa[now]=fat;h[now]=h[fat]+1;
     15     for(int i=fir[now];i;i=nex[i])
     16     if(to[i]!=fat)
     17         size[now]+=build(to[i],now),bro[to[i]]=son[now],son[now]=to[i];
     18     return size[now];
     19 }
     20 void pou(int now,int to)
     21 {
     22     l[++N]=now;pos[now]=N;top[now]=to;
     23     int max=son[now];
     24     if(!max) return;
     25     for(int i=bro[max];i;i=bro[i])
     26     if(size[i]>size[max]) max=i;
     27     pou(max,to);
     28     for(int i=son[now];i;i=bro[i])
     29     if(i!=max) pou(i,i);
     30 }
     31 void down(int now)////////////////////////////
     32 {
     33     if(t[now].b)
     34     {
     35         t[now].b=0;t[now*2].b=t[now*2+1].b=1;
     36         t[now*2].s=t[now*2+1].s=1;
     37         t[now*2].l=t[now*2].r=t[now*2+1].l=t[now*2+1].r=t[now].l;
     38     }
     39 }
     40 void work(int now,int l,int r,int x,int y,int z)
     41 {
     42     if(l==x && r==y)
     43     {    t[now]=(node){1,z,z,1};    return;}
     44     down(now);
     45     if(x<=mid)
     46         work(now*2,l,mid,x,min(y,mid),z);
     47     if(y>mid)
     48         work(now*2+1,mid+1,r,max(x,mid+1),y,z);
     49     t[now]=mix(t[now*2],t[now*2+1]);
     50 }
     51 node que(int now,int l,int r,int x,int y)
     52 {
     53     if(l==x && r==y)
     54         return t[now];
     55     down(now);
     56     if(y<=mid) return que(now*2,l,mid,x,y);
     57     if(x>mid) return que(now*2+1,mid+1,r,x,y);
     58     return mix(que(now*2,l,mid,x,mid),que(now*2+1,mid+1,r,mid+1,y));
     59 }
     60 void solve(int x,int y,int z)
     61 {
     62     bool b=0;ans[0]=ans[1]=(node){0,-1,-1,0};
     63     while(top[x]!=top[y])
     64     {
     65         if(h[top[x]]<h[top[y]]) swap(x,y),b=!b;
     66         if(z==-1) 
     67         {
     68             node tem=que(1,1,n,pos[top[x]],pos[x]);
     69             if(!b) swap(tem.l,tem.r);///////////////////////////////
     70             if(ans[b].s==0) ans[b]=tem;
     71             else
     72                 ans[b]=b?mix(tem,ans[b]):mix(ans[b],tem);
     73         }
     74         else
     75             work(1,1,n,pos[top[x]],pos[x],z);
     76         x=fa[top[x]];
     77     }
     78     if(h[x]>h[y]) swap(x,y),b=!b;//////////////////
     79     if(z==-1)
     80     {
     81         node tem=que(1,1,n,pos[x],pos[y]);b=!b;////////////////
     82         if(!b) swap(tem.l,tem.r);
     83         if(ans[b].s==0) ans[b]=tem;
     84         else
     85             ans[b]=b?mix(tem,ans[b]):mix(ans[b],tem);
     86         printf("%d
    ",mix(ans[0],ans[1]).s);
     87     }
     88     else
     89         work(1,1,n,pos[x],pos[y],z);
     90 }
     91 int main()
     92 {
     93     scanf("%d%d",&n,&M);
     94     for(int i=1;i<=n;i++)
     95         scanf("%d",&co[i]);
     96     for(int i=1;i<n;i++)
     97         scanf("%d%d",&p,&q),add(p,q),add(q,p);
     98     build(1,0);
     99     pou(1,1);
    100     for(int i=1;i<=n;i++)
    101         work(1,1,n,pos[i],pos[i],co[i]);
    102     for(int i=1;i<=M;i++)
    103     {
    104         char ch=getchar();
    105         while(ch!='C' && ch!='Q') ch=getchar();
    106         if(ch=='C')
    107             scanf("%d%d%d",&p,&q,&o),solve(p,q,o);
    108         else
    109             scanf("%d%d",&p,&q),solve(p,q,-1);
    110     }
    111     return 0;
    112 }
  • 相关阅读:
    【洛谷 4613】Olivander
    【洛谷 1385】密令
    【洛谷 4439】Aron
    【洛谷 3383】线性筛素数
    【洛谷 2412】查单词
    【洛谷 1980】计数问题
    【洛谷 3372】(模板)线段树 1
    Luogu P3743 kotori的设备
    Luogu P2340 [USACO03FALL]Cow Exhibition G
    Luogu P3047 [USACO12FEB]Nearby Cows G
  • 原文地址:https://www.cnblogs.com/wanglichao/p/5788962.html
Copyright © 2011-2022 走看看