BZOJ4999:This Problem Is Too Simple!(DFS序&树上差分&线段树动态开点:区间修改单点查询)
Description
Input
Output
Sample Input
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
1
1
0
题意:给定一个数,顶点有颜色。 Q次操作,或修改单点颜色,或查询路径颜色为x的个数。
思路:由于是路径,想到树剖+线段树,但是颜色个数无法合并,因此不行。 换个思路,用差分来求,然后把每个颜色弄个线段树,然后这个颜色的线段树单点代表的是这个点到根有多少这个颜色。 如果x点加了一个颜色为y的,那么以y这棵树,就再某个范围加1,这个范围是x的子树的DFS序范围;同理,减少则为-1 。
那么查询u到v路径为x颜色的个数,就在x这棵树上求sum[u]+sum[v]-sum[LCA]-sum[fa[LCA]];
自己写了一遍,感觉动态开点好像也没那么难。 但是为什么我的那么慢啊。
(颜色需要离散化。
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=;
struct in{
int lson,rson,lazy;
in(){lson=rson=lazy=;}
}s[maxn*];
struct qqq{
char opt[]; int u,v,x;
}q[maxn<<];
int dep[maxn],a[maxn],rt[maxn*],fa[maxn][],in[maxn],ou[maxn],Log[maxn];
int Laxt[maxn],Next[maxn<<],To[maxn<<],cnt,times,b[maxn*],tot;
void add(int u,int v){
Next[++cnt]=Laxt[u]; Laxt[u]=cnt; To[cnt]=v;
}
int LCA(int u,int v){
if(dep[u]<dep[v]) swap(u,v);
for(int i=Log[dep[u]-dep[v]];i>=;i--)
if(dep[fa[u][i]]>=dep[v]) u=fa[u][i];
if(u==v) return u;
for(int i=;i>=;i--)
if(fa[u][i]!=fa[v][i]) u=fa[u][i],v=fa[v][i];
return fa[u][];
}
void dfs(int u,int f){
in[u]=++times;dep[u]=dep[f]+;
for(int i=Laxt[u];i;i=Next[i])
if(To[i]!=f) dfs(To[i],u);
ou[u]=times; fa[u][]=f;
}
void pushdown(int Now){
if(s[Now].lazy!=){
if(!s[Now].lson) s[Now].lson=++cnt;
if(!s[Now].rson) s[Now].rson=++cnt;
s[s[Now].lson].lazy+=s[Now].lazy;
s[s[Now].rson].lazy+=s[Now].lazy;
s[Now].lazy=;
}
}
void addnum(int &Now,int L,int R,int l,int r,int add){
if(!Now) Now=++cnt;
if(l<=L&&r>=R){ s[Now].lazy+=add; return ; }
int Mid=(L+R)>>; pushdown(Now);
if(l<=Mid) addnum(s[Now].lson,L,Mid,l,r,add);
if(r>Mid) addnum(s[Now].rson,Mid+,R,l,r,add);
}
int query(int Now,int L,int R,int pos){
if(!Now) return ;
if(L==R) return s[Now].lazy;
int Mid=(L+R)>>; pushdown(Now);
if(pos<=Mid) return query(s[Now].lson,L,Mid,pos);
return query(s[Now].rson,Mid+,R,pos);
}
int main()
{
int N,Q,u,v,x;
scanf("%d%d",&N,&Q); rep(i,,N) Log[i]=Log[i>>]+;
rep(i,,N) scanf("%d",&a[i]),b[++tot]=a[i];
rep(i,,N-){
scanf("%d%d",&u,&v);
add(u,v); add(v,u);
}
dfs(,); cnt=;
rep(j,,)
rep(i,,N){
fa[i][j]=fa[fa[i][j-]][j-];
}
rep(i,,Q){
scanf("%s%d%d",q[i].opt,&q[i].u,&q[i].v);
if(q[i].opt[]=='Q') scanf("%d",&q[i].x),b[++tot]=q[i].x;
else b[++tot]=q[i].v;
}
sort(b+,b+tot+); tot=unique(b+,b+tot+)-(b+);
rep(i,,N) a[i]=lower_bound(b+,b+tot+,a[i])-b;
rep(i,,Q) {
if(q[i].opt[]=='Q') q[i].x=lower_bound(b+,b+tot+,q[i].x)-b;
else q[i].v=lower_bound(b+,b+tot+,q[i].v)-b;
}
rep(i,,N) addnum(rt[a[i]],,N,in[i],ou[i],);
rep(i,,Q){
u=q[i].u; v=q[i].v;
if(q[i].opt[]=='C'){
addnum(rt[a[u]],,N,in[u],ou[u],-); a[u]=v;
addnum(rt[a[u]],,N,in[u],ou[u],);
}
else {
x=q[i].x;
int Lca=LCA(u,v);
int res=query(rt[x],,N,in[u]);
res+=query(rt[x],,N,in[v]);
res-=query(rt[x],,N,in[Lca]);
res-=query(rt[x],,N,in[fa[Lca][]]);
printf("%d\n",res);
}
}
return ;
}
BZOJ4999:This Problem Is Too Simple!(DFS序&树上差分&线段树动态开点:区间修改单点查询)的更多相关文章
- BZOJ4771 七彩树(dfs序+树上差分+主席树)
		考虑没有深度限制怎么做.显然的做法是直接转成dfs序上主席树,但如果拓展到二维变成矩形数颜色数肯定没法做到一个log. 另一种做法是利用树上差分.对于同种颜色的点,在每个点处+1,dfs序相邻点的lc ... 
- Codeforces Round #442 (Div. 2) E Danil and a Part-time Job (dfs序加上一个线段树区间修改查询)
		题意: 给出一个具有N个点的树,现在给出两种操作: 1.get x,表示询问以x作为根的子树中,1的个数. 2.pow x,表示将以x作为根的子树全部翻转(0变1,1变0). 思路:dfs序加上一个线 ... 
- 【bzoj4771】七彩树  树链的并+STL-set+DFS序+可持久化线段树
		题目描述 给定一棵n个点的有根树,编号依次为1到n,其中1号点是根节点.每个节点都被染上了某一种颜色,其中第i个节点的颜色为c[i].如果c[i]=c[j],那么我们认为点i和点j拥有相同的颜色.定义 ... 
- hdu5692【dfs序】【线段树】
		Snacks Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Sub ... 
- 【62测试】【状压dp】【dfs序】【线段树】
		第一题: 给出一个长度不超过100只包含'B'和'R'的字符串,将其无限重复下去. 比如,BBRB则会形成 BBRBBBRBBBRB 现在给出一个区间[l,r]询问该区间内有多少个字符'B'(区间下标 ... 
- 【DFS序】【线段树】bzoj4034 [HAOI2015]T2
		分开维护树的入栈序和出栈序,用两棵线段树.回答时就是用一颗的减去另一棵的. #include<cstdio> #include<algorithm> using namespa ... 
- 【树链剖分】【dfs序】【线段树】bzoj2836 魔法树
		这道题告诉我们:树链剖分的重标号就是dfs序. #include<cstdio> #include<algorithm> using namespace std; #defin ... 
- 【BZOJ-3653】谈笑风生       DFS序 + 可持久化线段树
		3653: 谈笑风生 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 628 Solved: 245[Submit][Status][Discuss] ... 
- BZOJ 3653: 谈笑风生(DFS序+可持久化线段树)
		首先嘛,还是太弱了,想了好久QAQ 然后,这道题么,明显就是求sigma(size[x]) (x是y的儿子且层树小于k) 然后就可以发现:把前n个节点按深度建可持久化线段树,就能用前缀和维护了 其实不 ... 
随机推荐
- webservice声明发布SOAP1.2
			在不声明1.2的情况下,默认是1.1 当声明1.2时 
- caffe2+cuda+Ubuntu16.04(u盘安装)
			安装caffe2 预先准备.安装gflags及autoconf及GLOG https://github.com/caffe2/caffe2/issues/1810 一.下载源代码通过网盘 https: ... 
- MU puzzle
			2017-08-06 20:49:38 writer:pprp 三种操作: 1.MUI -> MUIUI 2.MUUU -> MU 3.MUIII -> MUU 分析:有两个操作:将 ... 
- sass的多种用法
			sass的多种用法 主要归纳总结sass的常见用法,作为个人笔记使用,部分知识点并不仔细讲解.具体可参考文档:sass官网 一.嵌套 .svg{ position: absolute; left: 0 ... 
- Python在线教程(廖雪峰)
			http://www.liaoxuefeng.com/wiki/001374738125095c955c1e6d8bb493182103fac9270762a000 
- 基于哈夫曼编码的压缩解压程序(C 语言)
			这个程序是研一上学期的课程大作业.当时,跨专业的我只有一点 C 语言和数据结构基础,为此,我查阅了不少资料,再加上自己的思考和分析,实现后不断调试.测试和完善,耗时一周左右,在 2012/11/19 ... 
- 2-3 sshd服务---暴力破解应对策略
			sshd服务暴力破解步骤 sshd暴力破解方法 防止暴力破解调优 1. 变更默认端口 2. 变更root用户 3. 日志监控-->防止暴力破解(fail2ban应用) fail2ban详解 ... 
- clipboard.js使用方法
			HTML data-clipboard-action=“ copy ” 或者“cut” data-clipboard-target="#domName" data-clipboa ... 
- UVA-11294 Wedding (2-SAT)
			题目大意:一张长桌,n对夫妻,编号为0~n,这些人要坐在长桌两侧,每对夫妻不能坐在同一侧.其中,有2*m个人相互讨厌,编号为0的夫妻中的妻子不愿意让对面那一侧中有两个相互吵过架的人,找一种排座位方案. ... 
- UVA-1623 Enter The Dragon (贪心)
			题目大意:有n个装满水的湖,m天.每天可能下雨也可能晴天,只要下雨就会把湖填满,若已满,则发洪水.有一台只能在晴天使用的抽水机,每次抽水只能抽一个湖,并且全部抽光.问是否存在一种使得不发洪水的抽水方案 ... 
