• <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

            題目描述

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

            吐槽:

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

            算法分析:

                1. 基于樹的動態(tài)統(tǒng)計,還是要先做樹鏈剖分
                2. 至于線段怎么維護是個問題,這里我的方法是: 線段樹記錄每個區(qū)間的顏色段數(shù),和最左段與最右段的顏色。更新的話要用到懶惰標記法。
                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 西月弦 閱讀(869) 評論(1)  編輯 收藏 引用 所屬分類: 解題報告

            FeedBack:
            # re: bzoj 2243 樹鏈剖分+線段樹
            2013-02-10 12:05 | silver__bullet
            樹鏈剖分之后,如果兩個點在樹的路徑中是連續(xù)的,而映射到線段樹上之后這兩個點不連續(xù),對于這種情況那怎么維護?  回復(fù)  更多評論
              
            日日躁夜夜躁狠狠久久AV| 精品久久人人做人人爽综合 | 久久久综合九色合综国产| 精品久久久无码中文字幕天天| 久久久久国产一区二区三区| 久久精品国产亚洲αv忘忧草| 精品国产一区二区三区久久| 久久久久人妻精品一区三寸蜜桃| 久久久久青草线蕉综合超碰| 99久久精品免费观看国产| 国内精品久久久人妻中文字幕| 三级片免费观看久久| 久久嫩草影院免费看夜色| 91亚洲国产成人久久精品| 精品免费tv久久久久久久| 波多野结衣中文字幕久久| 色欲av伊人久久大香线蕉影院| 久久久久亚洲av成人无码电影| 91精品国产综合久久婷婷| 久久亚洲私人国产精品vA| 亚洲AV日韩AV天堂久久| 囯产极品美女高潮无套久久久| 色狠狠久久综合网| 国产成人久久激情91| 无码八A片人妻少妇久久| 久久福利青草精品资源站免费| 欧美日韩中文字幕久久久不卡| 色婷婷综合久久久中文字幕| 久久国产精品无| 久久精品这里只有精99品| 国产精品综合久久第一页| 久久99国产精品一区二区| 久久精品视频网| 九九久久99综合一区二区| 91久久成人免费| 久久国产成人午夜AV影院| 久久久亚洲AV波多野结衣| 日产精品久久久一区二区| 婷婷久久综合九色综合九七| 欧美久久精品一级c片片| 亚洲人成网亚洲欧洲无码久久|