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个整数,表示初始时每个节点的初始值。
接下来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

Sample Output

0
1
1
0
————————————————————————————
这道题我写的扫描线 
我们把一个询问(u->v)拆成四个 
设根为1 
询问的答案就是1->u + 1->v - 1->lca(u,v) 1-fa[lca] 
然后修改的影响范围只有这个点的子树 这个可以用dfs序+树状数组实现
然后我们每一种权值建一棵树(权值需要离散化) 当然因为如果每次都初始化树状数组肯定会T
这里我利用了时间戳  这样之后就解决问题了 就是代码可能有点复杂QAQ
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
const int M=1e6+,mod=;
int read(){
int ans=,f=,c=getchar();
while(c<''||c>''){if(c=='-') f=-; c=getchar();}
while(c>=''&&c<=''){ans=ans*+(c-''); c=getchar();}
return ans*f;
}
int n,m,k,v[M],l[M],r[M],pos[M];
int first[M],cnt,ans[M],mark[M];
struct node{int to,next;}e[*M];
void ins(int a,int b){e[++cnt]=(node){b,first[a]}; first[a]=cnt;}
void insert(int a,int b){ins(a,b); ins(b,a);}
int dep[M],f[M][],sum;
void dfs(int x){
l[x]=pos[x]=++sum;
for(int i=;(<<i)<=dep[x];i++) f[x][i]=f[f[x][i-]][i-];
for(int i=first[x];i;i=e[i].next){
int now=e[i].to;
if(!dep[now]){
dep[now]=dep[x]+;
f[now][]=x;
dfs(now);
}
}r[x]=sum;
}
int find(int x,int y){
if(dep[x]<dep[y]) std::swap(x,y);
int d=dep[x]-dep[y];
for(int i=;(<<i)<=d;i++) if(<<i&d) x=f[x][i];
if(x==y) return x;
for(int i=;i>=;i--)
if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
return f[x][];
}
struct P{int s,x,T;};
std::vector<P>e1[M];
struct Q{int l,r,T;};
std::vector<Q>e2[M];
int star[mod],cnth;
struct H{int to,next;}hash[M];
int get(int x){
int w=x%mod;
for(int i=star[w];i;i=hash[i].next) if(hash[i].to==x) return i;
cnth++; hash[cnth].to=x; hash[cnth].next=star[w]; star[w]=cnth;
return cnth;
}
char c[];
int s[M],now[M];
int lowbit(int x){return x&-x;}
void add(int x,int ss){
while(x<=n){
if(now[x]!=k) now[x]=k,s[x]=;
s[x]+=ss;
x+=lowbit(x);
}
}
int query(int x){
int ans=;
while(x){
if(now[x]==k) ans+=s[x];
x-=lowbit(x);
}
return ans;
}
int main(){
n=read(); m=read();
for(int i=;i<=n;i++){
v[i]=get(read());
e1[v[i]].push_back((P){,i,});
}
int x,y;
for(int i=;i<n;i++) x=read(),y=read(),insert(x,y);
dep[]=; dfs();
for(int i=;i<=m;i++){
scanf("%s",c);
if(c[]=='C'){
x=read(); k=get(read());
if(v[x]==k) continue;
e1[k].push_back((P){,x,i});
e1[v[x]].push_back((P){-,x,i});
v[x]=k;
}
else{
mark[i]=;
x=read(); y=read(); k=get(read());
e2[k].push_back((Q){x,y,i});
}
}
for(k=;k<=cnth;k++){
int now=;
P* h1=e1[k].data();
Q* h2=e2[k].data();
for(int i=;i<e2[k].size();i++){
while(now<e1[k].size()&&h1[now].T<=h2[i].T){
add(l[h1[now].x],h1[now].s);
add(r[h1[now].x]+,-h1[now].s);
now++;
}
int id=h2[i].T;
ans[id]+=query(pos[h2[i].l]); ans[id]+=query(pos[h2[i].r]);
int lca=find(h2[i].l,h2[i].r),fa=f[lca][];
ans[id]-=query(pos[lca]); ans[id]-=query(pos[fa]);
}
}
for(int i=;i<=m;i++)if(mark[i]) printf("%d\n",ans[i]);
return ;
}

bzoj 4999: This Problem Is Too Simple!的更多相关文章

  1. BZOJ 4999: This Problem Is Too Simple! DFS序+LCA+树状数组+离线

    Code: #include<bits/stdc++.h> #define setIO(s) freopen(s".in","r",stdin) , ...

  2. [BZOJ 4999]This Problem Is Too Simple!

    [BZOJ 4999]This Problem Is Too Simple! 题目 给您一颗树,每个节点有个初始值. 现在支持以下两种操作: 1. C i x(0<=x<2^31) 表示将 ...

  3. 4999: This Problem Is Too Simple!

    Description 给您一颗树,每个节点有个初始值. 现在支持以下两种操作: C i x(0<=x<2^31) 表示将i节点的值改为x. Q i j x(0<=x<2^31 ...

  4. 【BZOJ4999】This Problem Is Too Simple!(线段树)

    [BZOJ4999]This Problem Is Too Simple!(线段树) 题面 BZOJ 题解 对于每个值,维护一棵线段树就好啦 动态开点,否则空间开不下 剩下的就是很简单的问题啦 当然了 ...

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

    [BZOJ4999]This Problem Is Too Simple! Description 给您一颗树,每个节点有个初始值. 现在支持以下两种操作: 1. C i x(0<=x<2 ...

  6. bzoj4999 This Problem Is Too Simple!

    Description 给您一颗树,每个节点有个初始值. 现在支持以下两种操作: 1. C i x(0<=x<2^31) 表示将i节点的值改为x. 2. Q i j x(0<=x&l ...

  7. 2019.03.09 bzoj4999: This Problem Is Too Simple!(树链剖分+线段树动态开点)

    传送门 题意:给一颗树,每个节点有个初始值,要求支持将i节点的值改为x或询问i节点到j节点的路径上有多少个值为x的节点. 思路: 考虑对每种颜色动态开点,然后用树剖+线段树维护就完了. 代码: #in ...

  8. BZOJ4999: This Problem Is Too Simple!树链剖分+动态开点线段树

    题目大意:将某个节点的颜色变为x,查询i,j路径上多少个颜色为x的点... 其实最开始一看就是主席树+树状数组+DFS序...但是过不去...MLE+TLE BY FCWWW 其实树剖裸的一批...只 ...

  9. BZOJ4999:This Problem Is Too Simple!(DFS序&树上差分&线段树动态开点:区间修改单点查询)

    Description 给您一颗树,每个节点有个初始值. 现在支持以下两种操作: 1. C i x(0<=x<2^31) 表示将i节点的值改为x. 2. Q i j x(0<=x&l ...

随机推荐

  1. golang 小知识点记录

    获取url中的参数及输出到页面的几种方式 func SayHello(w http.ResponseWriter, req *http.Request) { req.Method //获取url的方法 ...

  2. 使用Entity Framework出错

          在使用的过程中,写了一个例子,结果就报错说      The context cannot be used while the model is being created.      在 ...

  3. 「赛后补题」HBCPC2018题目代码与思路简析

    这次比赛(2018年第二届河北省大学生程序设计竞赛)虽然没有打,但是题目还是要写的.未完成的题目(还差比较硬核的四题)和思路分析会陆续更新完. Problem A 2011 Mex Query /* ...

  4. 用Fluent实现MySQL到ODPS数据集成

    安装ruby 首先通过 /etc/issue 命令查看当前使用centos是哪个版本: [hadoop@hadoop03 ~]$  cat /etc/issue 由于centos版本是6.6,安装ru ...

  5. Mapper的方式总结

    Mapper的方式总结: <mappers> <!-- 通过package元素将会把指定包下面的所有Mapper接口进行注册 --> <package name=&quo ...

  6. flask - 1

    from flask import Flask app = Flask(__name__) @app.route('/') def hello_world(): return 'Hello, Worl ...

  7. HDU 3269 P2P File Sharing System(模拟)(2009 Asia Ningbo Regional Contest)

    Problem Description Peer-to-peer(P2P) computing technology has been widely used on the Internet to e ...

  8. wpa_supplicant 初始化

    几个重要的结构体介绍: 1. struct wpa_interface --- Parameters for wpa_supplicant_add_iface(). wpa_interface对应网络 ...

  9. Daily Scrum02 12.02

    今天是黑色星期一,虽然大家最近被各种大作业压得身心疲惫,但是团队的凝聚力战胜了一切不快. 看看同志们今天的战绩,是不是又有一种充实感油然而生呢??? By Ryan Mao who? Today? T ...

  10. hadoop 2.6.0 伪分布式部署安装遇到的问题

    之前读到了一篇关于配置安装hadoop的博文(地址:http://www.powerxing.com/install-hadoop/)能正确安装和运行,但是在网页进行Jobtracker监控时,输入l ...