• <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 西月弦 閱讀(861) 評論(1)  編輯 收藏 引用 所屬分類: 解題報告

            FeedBack:
            # re: bzoj 2243 樹鏈剖分+線段樹
            2013-02-10 12:05 | silver__bullet
            樹鏈剖分之后,如果兩個點在樹的路徑中是連續的,而映射到線段樹上之后這兩個點不連續,對于這種情況那怎么維護?  回復  更多評論
              
            久久精品极品盛宴观看| 久久久久免费精品国产| 97久久香蕉国产线看观看| 久久久久久久人妻无码中文字幕爆| 浪潮AV色综合久久天堂| 久久精品这里热有精品| 香蕉久久永久视频| 97久久精品人妻人人搡人人玩| 88久久精品无码一区二区毛片| 99久久这里只精品国产免费| 久久Av无码精品人妻系列| 久久久受www免费人成| 久久水蜜桃亚洲av无码精品麻豆| 2020最新久久久视精品爱| 国内精品伊人久久久久777| 成人国内精品久久久久影院VR| 久久久久久久女国产乱让韩| 久久国产乱子伦精品免费强| 亚洲乱码精品久久久久..| 久久久久国产一级毛片高清板| av无码久久久久久不卡网站| 亚洲精品国产第一综合99久久| 99久久亚洲综合精品网站| 国产亚洲精品自在久久| 伊人久久大香线蕉亚洲五月天 | 一本一道久久综合狠狠老| 久久久久99精品成人片三人毛片| 国产精品久久久久…| 伊人久久大香线蕉综合影院首页| 久久久久久久91精品免费观看| 久久天天躁狠狠躁夜夜av浪潮| 精品久久久无码中文字幕天天| 四虎国产精品免费久久久| 九九99精品久久久久久| 77777亚洲午夜久久多喷| 欧美丰满熟妇BBB久久久| 少妇人妻88久久中文字幕| 久久国产精品无码HDAV| 久久精品国产福利国产秒| 国内精品伊人久久久久| 国产亚洲成人久久|