[BZOJ 4999]This Problem Is Too Simple!

[BZOJ 4999]This Problem Is Too Simple!

题目

给您一颗树,每个节点有个初始值。

现在支持以下两种操作:

1. C i x(0<=x<2^31) 表示将i节点的值改为x。

2. Q i j x(0<=x<2^31) 表示询问i节点到j节点的路径上有多少个值为x的节点。

INPUT

第一行有两个整数N,Q(1 ≤N≤ 100,000;1 ≤Q≤ 200,000),分别表示节点个数和操作个数。

下面一行N个整数,表示初始时每个节点的初始值。

接下来N-1行,每行两个整数x,y,表示x节点与y节点之间有边直接相连(描述一颗树)。

接下来Q行,每行表示一个操作,操作的描述已经在题目描述中给出。

OUTPUT

对于每个Q输出单独一行表示所求的答案。

SAMPLE

INPUT

5 6
10 20 30 40 50
1 2
1 3
3 4
3 5
Q 2 3 40
C 1 40
Q 2 3 40
Q 4 5 30
C 3 10
Q 4 5 30

OUTPUT

0

1

1

0

解题报告

树剖+权值线段树动态开点+离散

随便搞搞就行了

  1 #include<iostream>
  2 #include<cstring>
  3 #include<cstdio>
  4 #include<map>
  5 using namespace std;
  6 inline int read(){
  7     int sum(0);
  8     char ch(getchar());
  9     for(;ch<‘0‘||ch>‘9‘;ch=getchar());
 10     for(;ch>=‘0‘&&ch<=‘9‘;sum=sum*10+(ch^48),ch=getchar());
 11     return sum;
 12 }
 13 struct edge{
 14     int e;
 15     edge *n;
 16 }ed[200005],*pre[100005];
 17 int tot;
 18 inline void insert(int s,int e){
 19     ed[++tot].e=e;
 20     ed[tot].n=pre[s];
 21     pre[s]=&ed[tot];
 22 }
 23 map<int,int>ma;
 24 int num;
 25 int n,q;
 26 int a[100005];
 27 int dep[100005],size[100005],fa[100005],son[100005];
 28 inline void dfs1(int u){
 29     size[u]=1;
 30     son[u]=0;
 31     for(edge *i=pre[u];i;i=i->n){
 32         int e(i->e);
 33         if(e!=fa[u]){
 34             fa[e]=u;
 35             dep[e]=dep[u]+1;
 36             dfs1(e);
 37             size[u]+=size[e];
 38             if(size[e]>size[son[u]])
 39                 son[u]=e;
 40         }
 41     }
 42 }
 43 int timee;
 44 int id[100005],pos[100005],top[100005];
 45 inline void dfs2(int u,int rt){
 46     top[u]=rt;
 47     id[u]=++timee;
 48     pos[timee]=u;
 49     if(son[u])
 50         dfs2(son[u],rt);
 51     for(edge *i=pre[u];i;i=i->n){
 52         int e(i->e);
 53         if(e!=fa[u]&&e!=son[u])
 54             dfs2(e,e);
 55     }
 56 }
 57 int cnt;
 58 int rt[300005],lch[12000005],rch[12000005],sum[12000005];
 59 inline void update(int &x,int pos,int w,int l,int r){
 60     if(!x)
 61         x=++cnt;
 62     sum[x]+=w;
 63     if(l==r)
 64         return;
 65     int mid((l+r)>>1);
 66     if(pos<=mid)
 67         update(lch[x],pos,w,l,mid);
 68     else
 69         update(rch[x],pos,w,mid+1,r);
 70 }
 71 inline int query(int x,int ll,int rr,int l,int r){
 72     if(!x)
 73         return 0;
 74     if(ll<=l&&r<=rr)
 75         return sum[x];
 76     int mid((l+r)>>1),ret(0);
 77     if(ll<=mid)
 78         ret+=query(lch[x],ll,rr,l,mid);
 79     if(mid<rr)
 80         ret+=query(rch[x],ll,rr,mid+1,r);
 81     return ret;
 82 }
 83 inline int ask(int x,int y,int z){
 84     int ret(0),tmp(ma[z]);
 85     while(top[x]^top[y]){
 86         if(dep[top[x]]<dep[top[y]])
 87             swap(x,y);
 88         ret+=query(rt[tmp],id[top[x]],id[x],1,n);
 89         x=fa[top[x]];
 90     }
 91     if(dep[x]>dep[y])
 92         swap(x,y);
 93     ret+=query(rt[tmp],id[x],id[y],1,n);
 94     return ret;
 95 }
 96 char op[2];
 97 int main(){
 98     memset(pre,NULL,sizeof(pre));
 99     n=read(),q=read();
100     for(int i=1;i<=n;++i)
101         a[i]=read();
102     for(int i=1;i<n;++i){
103         int x(read()),y(read());
104         insert(x,y),insert(y,x);
105     }
106     dfs1(1);
107     dfs2(1,1);
108     for(int i=1;i<=n;++i){
109         if(!ma[a[i]])
110             ma[a[i]]=++num;
111         update(rt[ma[a[i]]],id[i],1,1,n);
112     }
113     while(q--){
114         scanf("%s",op);
115         if(op[0]==‘C‘){
116             int x(read()),y(read());
117             update(rt[ma[a[x]]],id[x],-1,1,n);
118             if(!ma[y])
119                 ma[y]=++num;
120             a[x]=y;
121             update(rt[ma[y]],id[x],1,1,n);
122         }
123         else{
124             int x(read()),y(read()),z(read());
125             if(!ma[z])
126                 puts("0");
127             else
128                 printf("%d\n",ask(x,y,z));
129         }
130     }
131 }

时间: 2024-10-10 08:15:54

[BZOJ 4999]This Problem Is Too Simple!的相关文章

bzoj 4999 This Problem Is Too Simple!

题目大意: 给一颗树,每个节点有个初始值 现在支持以下两种操作: 1. C i x 表示将i节点的值改为x 2. Q i j x 表示询问i节点到j节点的路径上有多少个值为x的节点 思路: 首先可以想到树链剖分 虽然颜色的数量看起来很吓人 但是实际上只可能有n+q种颜色 所以我们的线段树只需要像主席树那样去写就可以了 1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstdl

【BZOJ4999】This Problem Is Too Simple! 离线+树状数组+LCA

[BZOJ4999]This Problem Is Too Simple! Description 给您一颗树,每个节点有个初始值. 现在支持以下两种操作: 1. C i x(0<=x<2^31) 表示将i节点的值改为x. 2. Q i j x(0<=x<2^31) 表示询问i节点到j节点的路径上有多少个值为x的节点. Input 第一行有两个整数N,Q(1 ≤N≤ 100,000:1 ≤Q≤ 200,000),分别表示节点个数和操作个数. 下面一行N个整数,表示初始时每个节点的初

【BZOJ】【3489】A simple rmq problem

KD-Tree(乱搞) Orz zyf教给蒟蒻做法 蒟蒻并不会这题正解……(可持久化树套树?...Orz 对于每个点,我们可以求出pre[i],nex[i],那么询问的答案就是:求max (a[i]),其中 i 满足$ ( pre[i]<ql \ and \ nex[i]>qr\ and\ i \in [ql,qr] ) $ 然后我们以(i,pre[i],nex[i])为坐标……将所有点抽象到三维空间中,每次查询就相当于是一次区域求最值! 这题我的感受: 因为前面做了两道区域求和的……然后思路

BZOJ 2301: [HAOI2011]Problem b(莫比乌斯反演 + 容斥原理 + 分块优化)

传送门 Problem 2301. – [HAOI2011]Problem b 2301: [HAOI2011]Problem b Time Limit: 50 Sec  Memory Limit: 256 MBSubmit: 3671  Solved: 1643[Submit][Status][Discuss] Description 对于给出的n个询问,每次求有多少个数对(x,y),满足a≤x≤b,c≤y≤d,且gcd(x,y) = k,gcd(x,y)函数为x和y的最大公约数. Input

BZOJ 2302: [HAOI2011]Problem c( dp )

dp(i, j)表示从i~N中为j个人选定的方案数, 状态转移就考虑选多少人为i编号, 然后从i+1的方案数算过来就可以了. 时间复杂度O(TN^2) --------------------------------------------------------------------- #include<cstdio> #include<algorithm> #include<cstring> using namespace std; typedef long lo

[BZOJ 2301] [HAOI2011] Problem b

2301: [HAOI2011]Problem b Time Limit: 50 SecMemory Limit: 256 MB Description 对于给出的n个询问,每次求有多少个数对(x,y),满足a≤x≤b,c≤y≤d,且gcd(x,y) = k,gcd(x,y)函数为x和y的最大公约数. Input 第一行一个整数n,接下来n行每行五个整数,分别表示a.b.c.d.k Output 共n行,每行一个整数表示满足要求的数对(x,y)的个数 Sample Input 2 2 5 1 5

bzoj 2301: [HAOI2011]Problem b mobius反演 RE

http://www.lydsy.com/JudgeOnline/problem.php?id=2301 设f(i)为在区间[1, n]和区间[1, m]中,gcd(x, y) = i的个数. 设F(i)为在区间[1, n]和区间[1, m]中,gcd(x, y) % i == 0的个数,很简单的公式就是floor(n / i) * floor(m / i) 可知gcd(x, y) = k * i也属于F(i)的范围,所以可以反演得到f(i)的表达式. 算一次复杂度O(n),而且询问区间的时候要

BZOJ 2301([HAOI2011]Problem b-mobius反演)

2301: [HAOI2011]Problem b Time Limit: 50 Sec  Memory Limit: 256 MB Submit: 2170  Solved: 934 [Submit][Status][Discuss] Description 对于给出的n个询问,每次求有多少个数对(x,y),满足a≤x≤b,c≤y≤d,且gcd(x,y) = k,gcd(x,y)函数为x和y的最大公约数. Input 第一行一个整数n,接下来n行每行五个整数,分别表示a.b.c.d.k Out

BZOJ 2301 [HAOI2011]Problem b (容斥+莫比乌斯反演+分块优化 详解)

2301: [HAOI2011]Problem b Time Limit: 50 Sec  Memory Limit: 256 MB Submit: 2096  Solved: 909 [Submit][Status][Discuss] Description 对于给出的n个询问,每次求有多少个数对(x,y),满足a≤x≤b,c≤y≤d,且gcd(x,y) = k,gcd(x,y)函数为x和y的最大公约数. Input 第一行一个整数n,接下来n行每行五个整数,分别表示a.b.c.d.k Out