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 }
  • 相关阅读:
    3、spring注解注入
    2、spring注入のArrayList数组对象注入方式
    1、基本知识
    1、log4j的配置与使用
    3、在Eclipse中使用JUnit4进行单元测试(高级篇)
    2、在Eclipse中使用JUnit4进行单元测试(中级篇)
    1、JUnit4简介
    使用BroadcastReceiver实现系统对手机电量进行提示
    使用BroadcastReceiver监听系统接收的短信
    使用BroadcastReceiver实现开机自动运行的Service
  • 原文地址:https://www.cnblogs.com/HLAUV/p/9897470.html
Copyright © 2011-2022 走看看