• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            算法學社
            記錄難忘的征途
            posts - 141,comments - 220,trackbacks - 0

            題目描述

               在一顆點數為N<100,000的樹上,每個點有一個顏色。請你實現兩種操作 1. 給一段路徑u->v染色 2. 詢問路徑u->v上有多少種顏色

            吐槽:

                1. 4KB的代碼...
                2. 唉.... 這題的思路非常好想... 但是我還是捉了好久....真弱...
                3. 我盡量把代碼寫的清楚了...

            算法分析:

                1. 基于樹的動態統計,還是要先做樹鏈剖分
                2. 至于線段怎么維護是個問題,這里我的方法是: 線段樹記錄每個區間的顏色段數,和最左段與最右段的顏色。更新的話要用到懶惰標記法。
                3. 比維護/查詢邊要好寫吧....

              1
             // figo 5.16.2012
              2 // template & head file
              3 #include<cassert>
              4 #include<iostream>
              5 #include<cstdio>
              6 #include<cstring>
              7 using namespace std;
              8 template <typename T> inline void chkmin(T &a,const T b) { if(a > b) a = b;}
              9 template <typename T> inline void chkmax(T &a,const T b) { if(a < b) a = b;}
             10 // graph
             11 const int V = 100005;
             12 const int E = V * 2;
             13 int head[V],pnt[E],nxt[E],color[V],e,n;
             14 void add_edge(int u,int v){
             15     nxt[e] = head[u];
             16     head[u] = e;
             17     pnt[e] = v;
             18     e ++;
             19 }
             20 // segment tree
             21 int LT,RT;
             22 int lt[V<<2], rt[V<<2] ,clr[V<<2], cover[V<<2];
             23 void pushdown(int pos,int L,int R){
             24     if(L == R){ return;}
             25     if(cover[pos] == 1) {
             26         cover[pos]= 0;
             27         clr[pos<<1] = clr[pos<<1|1] = 1;
             28         lt[pos<<1] = rt[pos<<1] = lt[pos<<1|1] = rt[pos<<1|1] = lt[pos];
             29         cover[pos<<1] = cover[pos<<1|1] = 1;
             30     }
             31 }
             32 void upt(int pos,int L,int R){
             33     if(L==R) return;
             34     lt[pos] = lt[pos << 1];
             35     rt[pos] = rt[pos << 1 | 1];
             36     clr[pos] = clr[pos<<1] + clr[pos<<1|1] - (rt[pos<<1]==lt[pos<<1|1]);
             37 }
             38 int __ans,__last;
             39 void update(int l,int r,int pos,int L,int R,char cmd,int c = 0){
             40     if(L >= l && R <= r){
             41         if(cmd == 'C'){
             42             cover[pos] = clr[pos] = 1;
             43             lt[pos] = rt[pos] = c;
             44         }
             45         if(L == l) LT = lt[pos];
             46         if(R == r) RT = rt[pos];
             47         __ans += clr[pos] - (__last==lt[pos]);
             48         __last = rt[pos];
             49         return;
             50     }
             51     pushdown(pos,L,R);
             52     int mid = L + R >> 1;
             53     if(mid >= l) update(l,r,pos << 1, L, mid,cmd, c);
             54     if(mid < r) update(l,r,pos<<1|1, mid+1,R,cmd, c);
             55     upt(pos,L,R);
             56 }
             57 // dsu
             58 int parent[V];
             59 int find(int u){
             60     return u == parent[u] ? u : parent[u] = find(parent[u]);
             61 }
             62 // divide and conquer
             63 const int inf = ~0u>>2;
             64 int sz[V],P[V],heavy[V],deep[V],flag[V];
             65 int dfs(int u,int f){
             66     int mx = -1, s = -1;
             67     sz[u] = 1;
             68     for(int i = head[u];i!=-1; i = nxt[i]){
             69         int v = pnt[i];
             70         if(v == f) continue;
             71         deep[v] = deep[u] + 1;
             72         P[v] = u;
             73         dfs(v,u);
             74         sz[u] += sz[v];
             75         if(sz[v] > mx){
             76             mx = sz[v]; s = v;
             77         }
             78     }
             79     heavy[u] = s;
             80     if(s >= 0) parent[s] = u;
             81 }
             82 int prepare(){
             83     for(int i =0; i<n; i++) parent[i] = i;
             84     deep[0] = 0;P[0] = -1;
             85     dfs(0,0);
             86     int segsz = 0;
             87     for(int i=0; i<n; i++) if(heavy[i] == -1){
             88         int v = i;
             89         while(v && heavy[P[v]] == v){
             90             update(segsz,segsz,1,0,n,'C',color[v]);
             91             flag[v] = segsz ++;
             92             v = P[v];
             93         }
             94         update(segsz,segsz,1,0,n,'C',color[v]);
             95         flag[v] = segsz ++;
             96     }
             97     assert(segsz==n);
             98 }
             99 // operator
            100 int lca(int u,int v){
            101     while(1){
            102         int U = find(u);
            103         int V = find(v);
            104         if(U == V) return deep[u] < deep[v] ? u : v;
            105         else if(deep[U] >= deep[V])
            106             u = P[U];
            107         else v = P[V];
            108     }
            109 }
            110 int query(int u,int p,char cmd,int c=0){
            111     int ans = 0;
            112     int last = -1;
            113     while(u != P[p]){
            114         int l = flag[u];
            115         int v = find(u);
            116         if(deep[v]<deep[p]) v = p;
            117         int r = flag[v];
            118         __ans =0; __last = -1;
            119         update(l,r,1,0,n,cmd,c);
            120         ans += __ans - (LT == last);
            121         last = RT;
            122         u = P[v];
            123     }
            124     return ans;
            125 }
            126 // main
            127 int ask(int u,int v,char cmd,int c=0){
            128     int p = lca(u,v);
            129     return query(u,p,cmd,c) + query(v,p,cmd,c) - 1;
            130 }
            131 int main(){
            132     int m,u,v;
            133     scanf("%d%d",&n,&m);
            134     e = 0;
            135     for(int i=0;i<n;i++) head[i] = -1;
            136     for(int i=0;i<n;i++) scanf("%d",&color[i]);
            137     for(int i=1;i<n;i++){
            138         scanf("%d%d",&u,&v);
            139         u--; v--;
            140         add_edge(u,v);
            141         add_edge(v,u);
            142     }
            143     prepare();
            144     char cmd[2];int c=0;
            145     while(m--){
            146         scanf("%s%d%d",cmd,&u,&v);
            147         u--; v--;
            148         if(cmd[0]=='C') scanf("%d",&c);
            149         int ans = ask(u,v,cmd[0],c);
            150         if(cmd[0]=='Q') printf("%d\n",ans);
            151     }
            152 }
            posted on 2012-05-16 17:10 西月弦 閱讀(862) 評論(1)  編輯 收藏 引用 所屬分類: 解題報告

            FeedBack:
            # re: bzoj 2243 樹鏈剖分+線段樹
            2013-02-10 12:05 | silver__bullet
            樹鏈剖分之后,如果兩個點在樹的路徑中是連續的,而映射到線段樹上之后這兩個點不連續,對于這種情況那怎么維護?  回復  更多評論
              
            久久精品国产只有精品2020| 久久亚洲中文字幕精品一区| 久久亚洲国产最新网站| 亚洲AV无码1区2区久久| 国产精品久久久久久福利漫画| 中文字幕无码久久人妻| 一级做a爱片久久毛片| 欧美日韩精品久久免费| 国产精品美女久久久久久2018| 要久久爱在线免费观看| 久久国产精品成人片免费| 久久中文字幕人妻熟av女| 久久99精品久久久久子伦| 精品无码人妻久久久久久| 久久99国产精品一区二区| 亚洲国产成人久久笫一页| 久久99精品国产一区二区三区| 久久久国产亚洲精品| 国产精品成人99久久久久91gav| 国产成年无码久久久久毛片| 精品乱码久久久久久夜夜嗨| 久久久精品2019免费观看| 色欲综合久久躁天天躁| 久久亚洲视频| 亚洲精品tv久久久久| 国内精品久久久久久久久电影网| 97精品伊人久久久大香线蕉| 偷窥少妇久久久久久久久| 久久久久九国产精品| 欧美亚洲国产精品久久| 久久中文字幕无码专区| 久久久久国色AV免费看图片| 伊人色综合久久天天| 国产日产久久高清欧美一区| 久久精品国产亚洲AV嫖农村妇女| 精品国产青草久久久久福利| 精品人妻久久久久久888| 亚洲午夜久久久影院| 亚洲伊人久久精品影院| 人妻无码久久一区二区三区免费 | 亚洲国产精品久久久久婷婷老年|