zoukankan      html  css  js  c++  java
  • 【NOI省选模拟】小奇的花园

    「题目背景」

    小奇在家中的花园漫步时,总是会思考一些奇怪的问题。

    「问题描述」

    小奇的花园有n个温室,标号为1到n,温室以及以及温室间的双向道路形成一棵树。

    每个温室都种植着一种花,随着季节的变换,温室里的花的种类也在不断发生着变化。

    小奇想知道从温室x走到温室y的路径中(包括两个端点),第t种花出现的次数。

    「输入格式」

    第一行为两个整数n,q,表示温室的数目和操作的数目。

    第二行有n个整数T1,T2…Tn其中Ti表示温室i中的花的种类。

    接下来n-1行,每个两个整数x, y,表示温室x和y之间有一条双向道路。

    接下来q行,表示q个操作,分别为以下两种形式之一:

    • C x t 表示在温室x中的花的种类变为t。

    • Q x y t 表示询问温室x走到温室y的路径中(包括两个端点),第t种花出现

    的次数。

    为了体现在线操作,输入数据中的每个操作的参数都进行了加密。记最后一次询问的答案为anslast(一开始设anslast为0),下次读入中的x,y,t均需要异或上anslast以得到真实值,在C/C++中异或为ˆ运算符,在pascal中为xor运算符。

    「输出格式」

    输出q行,每行一个正整数表示该次询问答案。

    「样例输入」

    5 8

    10 20 30 40 50

    1 2

    1 3

    3 4

    3 5

    Q 2 5 10

    C 2 21

    Q 3 4 21

    C 6 22

    Q 1 7 28

    C 5 20

    Q 2 5 20

    Q 2 0 9

    「样例输出」

    1

    2

    0

    3

    1

    「样例解释」

    加密前的操作:

    Q 2 5 10

    C 3 20

    Q 2 5 20

    C 4 20

    Q 3 5 30

    C 5 20

    Q 2 5 20

    Q 1 3 10

    「数据范围」

    对于30%的数据,有n <= 1000, q <= 2000。

    对于50%的数据,有n <= 10000, q <= 20000。

    对于100%的数据,有n <= 100000, q <= 200000,0 <= T < 2^31。


     

      小奇

     

    下面的题解都是自己的话:

    50%

    既然强制在线,那我们就在线模拟,没什么方法,就一步步地往上找LCA并统计答案然后输出就好啦~

    考场上实在没办法AC拿50分也不吃亏。

    100%

    有一个转化很重要。

    我们可以通过类似求树上两点路径长度 dis=dep[x]+dep[y]-dep[LCA]*2 的方法,用s[i]表示从根节点到此时的i点col颜色的出现次数。

    所以每次在某个节点的某个颜色出现次数增加1时,它的整个子树的每个节点的s[i]都会增加1,那么从x到y某个颜色的出现次数显然就变成 s[x]+s[y]-s[LCA]*2+val[LCA]了

    那这样题目要求的单点修改、区间查询就被我们变成子树修改、单点查询了。子树修改用DFS序来看其实也就是区间修改了,可以用线段树解决。

    但是颜色种类那么多怎么办呢(而且数值还那么大)?

    可以用map来维护颜色编号,用动态开点线段树的方式对每一种颜色维护一棵线段树。

     

    做本题是参考了黄学长Hzwer的题解和程序,代码可能有相似之处,但线段树的操作绝对是我自己的风格。(求资瓷~)

     

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstdlib>
      4 #include<cstring>
      5 #include<algorithm>
      6 #include<map>
      7 
      8 #define For(i,a,b)for(register int i=a;i<=b;++i)
      9 #define Dwn(i,a,b)for(register int i=a;i>=b;--i)
     10 #define Re register
     11 #define Pn putchar('
    ')
     12 
     13 using namespace std;
     14 
     15 const int N=1e5+5,Nr=1e7+5;
     16 int head[N],nxt[N*2],v[N*2],cnt=1;
     17 int f[N][21],dfx[N],dID=0,dep[N],sz[N];
     18 int rt[N*3],ls[Nr],rs[Nr],tag[Nr],tr[Nr],tID=0;
     19 int n,m,x,y,T[N*3],cID=0,t,Q,ans=0;
     20 map<int,int>mp;
     21 inline void read(int &v){
     22     v=0;
     23     char c=getchar();
     24     while(c<'0'||c>'9')c=getchar();
     25     while(c>='0'&&c<='9')v=v*10+c-'0',c=getchar();
     26 }
     27 void write(int x){
     28     if(x>9)write(x/10);
     29     int xx=x%10;
     30     putchar(xx+'0');
     31 }
     32 void add(int ux,int vx){
     33     cnt++;
     34     nxt[cnt]=head[ux]; head[ux]=cnt; v[cnt]=vx;
     35     cnt++;
     36     nxt[cnt]=head[vx]; head[vx]=cnt; v[cnt]=ux;
     37 }
     38 
     39 void DFS(int x,int fa){
     40     sz[x]=1;
     41     dfx[x]=++dID;
     42     for(Re int i=head[x];i;i=nxt[i]){
     43         int vv=v[i];
     44         if(vv==fa)continue;
     45         dep[vv]=dep[x]+1;
     46         f[vv][0]=x;
     47         DFS(vv,x);
     48         sz[x]+=sz[vv];
     49     }
     50 }
     51 
     52 int LCA(int x,int y){
     53     if(dep[x]<dep[y])swap(x,y);
     54     Dwn(b,20,0)if(f[x][b]!=-1){
     55         if(dep[f[x][b]]>=dep[y])x=f[x][b];
     56     }
     57     if(x==y)return x;
     58     Dwn(b,20,0)if(f[x][b]!=-1&&f[y][b]!=-1&&f[x][b]!=f[y][b]){
     59         x=f[x][b]; y=f[y][b];
     60     }
     61     return f[x][0];
     62 }
     63 
     64 
     65 void pDown(int o,int l,int r){
     66     if(!tag[o]||l==r)return;
     67     int tg=tag[o]; tag[o]=0;
     68     if(!ls[o])ls[o]=++tID;
     69     if(!rs[o])rs[o]=++tID;
     70     tr[ls[o]]+=tg; tag[ls[o]]+=tg;
     71     tr[rs[o]]+=tg; tag[rs[o]]+=tg;
     72 }
     73 
     74 void Ins(int &o,int l,int r,int lx,int rx,int dt){
     75     if(!o)o=++tID;
     76     if(lx<=l&&rx>=r){
     77         tr[o]+=dt; tag[o]+=dt;
     78         return;
     79     }
     80     pDown(o,l,r);
     81     int m=(l+r)>>1;
     82     if(lx<=m)Ins(ls[o],l,m,lx,rx,dt);
     83     if(rx>m)Ins(rs[o],m+1,r,lx,rx,dt);
     84 }
     85 
     86 int Qry(int o,int l,int r,int px){
     87     if(!o)return 0;
     88     if(l==r)return tr[o];
     89     pDown(o,l,r);
     90     int m=(l+r)>>1;
     91     if(px<=m)return Qry(ls[o],l,m,px);
     92     else return Qry(rs[o],m+1,r,px);
     93 }
     94 
     95 
     96 int main(){
     97     freopen("garden.in","r",stdin);
     98     freopen("garden.out","w",stdout);
     99     read(n); read(Q);
    100     For(i,1,n){
    101         read(t);
    102         if(!mp[t])mp[t]=++cID;
    103         T[i]=mp[t];
    104     }
    105     For(i,1,n-1){
    106         read(x); read(y);
    107         add(x,y);
    108     }
    109     
    110     memset(f,-1,sizeof(f));
    111     DFS(1,0);
    112     For(b,1,20) For(i,1,n){
    113         if(f[i][b-1]==-1)continue;
    114         f[i][b]=f[ f[i][b-1] ][b-1];
    115     }
    116     
    117     For(i,1,n){
    118         int lx=dfx[i];
    119         int rx=dfx[i]+sz[i]-1;
    120         Ins(rt[T[i]],1,n,lx,rx,1);
    121     }
    122     
    123     For(i,1,Q){
    124         
    125         char opt=getchar();
    126         while(opt!='C'&&opt!='Q')opt=getchar();
    127         if(opt=='C'){
    128             read(x); read(t);
    129             x^=ans; t^=ans;
    130             if(!mp[t])mp[t]=++cID;
    131             t=mp[t];
    132             int lx=dfx[x],rx=dfx[x]+sz[x]-1;
    133             
    134             Ins(rt[T[x]],1,n,lx,rx,-1);
    135             Ins(rt[t],1,n,lx,rx,1);
    136             T[x]=t;
    137         }
    138         if(opt=='Q'){
    139             read(x); read(y); read(t);
    140             x^=ans; y^=ans; t^=ans;
    141             if(!mp[t])mp[t]=++cID;
    142             t=mp[t];
    143             int xy=LCA(x,y);
    144             int fn;
    145             fn=Qry(rt[t],1,n,dfx[x])+Qry(rt[t],1,n,dfx[y]);
    146             fn-=Qry(rt[t],1,n,dfx[xy])*2;
    147             if(T[xy]==t)fn++;
    148             ans=fn;
    149             write(fn); Pn;
    150         }
    151     }
    152     fclose(stdin); fclose(stdout);
    153     return 0;
    154 }
  • 相关阅读:
    POJ 1300 Open Door
    POJ 2230 Watchcow
    codevs 1028 花店橱窗布置
    codevs 1021 玛丽卡
    codevs 1519 过路费
    codevs 3287 货车运输
    codevs 3305 水果姐逛水果街二
    codevs 1036 商务旅行
    codevs 4605 LCA
    POJ 1330 Nearest Common Ancestors
  • 原文地址:https://www.cnblogs.com/HLAUV/p/9897470.html
Copyright © 2011-2022 走看看