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

题解:由于每种颜色相互独立,可以考虑离线。将修改操作变成一个颜色的删除操作和另一个颜色的加入操作,然后将所有操作和询问都按颜色和时间排序,分别处理每一个颜色。然后我们只需要倍增LCA+动态维护所有点到根路径上的权值即可。单点权值+a等于它子树中所有点到根路径上的权值都+a,所以用树状数组维护DFS序即可。

竟然因为数组开小而WA了一天~

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn=200010;
int n,m,Q,cnt,now,tot;
struct node
{
int col,x,val,tim;
}p[maxn*5];
struct QUERY
{
int col,a,b,tim,org;
}q[maxn];
char str[10];
int to[maxn<<1],next[maxn<<1],head[maxn],p1[maxn],p2[maxn],dep[maxn],fa[19][maxn],v[maxn];
int Log[maxn],s[maxn],vis[maxn],ans[maxn];
void add(int a,int b)
{
to[cnt]=b,next[cnt]=head[a],head[a]=cnt++;
}
void dfs(int x)
{
p1[x]=++p2[0];
for(int i=head[x];i!=-1;i=next[i]) if(to[i]!=fa[0][x])
fa[0][to[i]]=x,dep[to[i]]=dep[x]+1,dfs(to[i]);
p2[x]=p2[0];
}
bool cmpp(node a,node b)
{
return (a.col==b.col)?(a.tim<b.tim):(a.col<b.col);
}
bool cmpq(QUERY a,QUERY b)
{
return (a.col==b.col)?(a.tim<b.tim):(a.col<b.col);
}
void updata(int x,int val)
{
for(int i=x;i<=n;i+=i&-i)
{
if(vis[i]<now) vis[i]=now,s[i]=0;
s[i]+=val;
}
}
int query(int x)
{
int i,ret=0;
for(i=x;i;i-=i&-i)
{
if(vis[i]<now) vis[i]=now,s[i]=0;
ret+=s[i];
}
return ret;
}
int lca(int a,int b)
{
if(dep[a]<dep[b]) swap(a,b);
for(int i=Log[dep[a]-dep[b]];i>=0;i--) if(dep[fa[i][a]]>=dep[b]) a=fa[i][a];
if(a==b) return a;
for(int i=Log[dep[a]];i>=0;i--) if(fa[i][a]!=fa[i][b]) a=fa[i][a],b=fa[i][b];
return fa[0][a];
}
inline int rd()
{
int ret=0,f=1; char gc=getchar();
while(gc<'0'||gc>'9') {if(gc=='-')f=-f; gc=getchar();}
while(gc>='0'&&gc<='9') ret=ret*10+gc-'0',gc=getchar();
return ret*f;
}
int main()
{
n=rd(),m=rd();
int i,j,a,b,c;
memset(head,-1,sizeof(head));
for(i=1;i<=n;i++) v[i]=p[++tot].col=rd(),p[tot].x=i,p[tot].tim=0,p[tot].val=1;
for(i=2;i<=n;i++) a=rd(),b=rd(),add(a,b),add(b,a);
dep[1]=1,dfs(1);
for(i=2;i<=n;i++) Log[i]=Log[i>>1]+1;
for(j=1;(1<<j)<=n;j++) for(i=1;i<=n;i++) fa[j][i]=fa[j-1][fa[j-1][i]];
for(i=1;i<=m;i++)
{
scanf("%s",str),a=rd(),b=rd();
if(str[0]=='C')
{
tot+=2,p[tot-1].x=p[tot].x=a,p[tot-1].col=v[a],v[a]=p[tot].col=b;
p[tot-1].tim=p[tot].tim=i,p[tot-1].val=-1,p[tot].val=1;
}
else q[++Q].a=a,q[Q].b=b,q[Q].col=rd(),q[Q].org=Q,q[Q].tim=i;
}
sort(p+1,p+tot+1,cmpp);
sort(q+1,q+Q+1,cmpq);
for(i=j=1;i<=Q;i++)
{
for(;(p[j].col<q[i].col||(p[j].col==q[i].col&&p[j].tim<q[i].tim))&&j<=tot;j++)
{
now=p[j].col;
updata(p1[p[j].x],p[j].val),updata(p2[p[j].x]+1,-p[j].val);
}
if(now==q[i].col)
{
a=q[i].a,b=q[i].b,c=lca(a,b);
ans[q[i].org]=query(p1[a])+query(p1[b])-query(p1[c])-query(p1[fa[0][c]]);
}
}
for(i=1;i<=Q;i++) printf("%d\n",ans[i]);
return 0;
}

【BZOJ4999】This Problem Is Too Simple! 离线+树状数组+LCA的更多相关文章

  1. HDU 5293 Annoying problem 树形dp dfs序 树状数组 lca

    Annoying problem 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5293 Description Coco has a tree, w ...

  2. HDU 5293 Tree chain problem 树形dp+dfs序+树状数组+LCA

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5293 题意: 给你一些链,每条链都有自己的价值,求不相交不重合的链能够组成的最大价值. 题解: 树形 ...

  3. 13年山东省赛 Boring Counting(离线树状数组or主席树+二分or划分树+二分)

    转载请注明出处: http://www.cnblogs.com/fraud/          ——by fraud 2224: Boring Counting Time Limit: 3 Sec   ...

  4. Educational Codeforces Round 10 D. Nested Segments 离线树状数组 离散化

    D. Nested Segments 题目连接: http://www.codeforces.com/contest/652/problem/D Description You are given n ...

  5. Codeforces Round #365 (Div. 2) D - Mishka and Interesting sum(离线树状数组)

    http://codeforces.com/contest/703/problem/D 题意: 给出一行数,有m次查询,每次查询输出区间内出现次数为偶数次的数字的异或和. 思路: 这儿利用一下异或和的 ...

  6. HDU 4417 离线+树状数组

    Super Mario Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

  7. bzoj 2434: 阿狸的打字机 fail树+离线树状数组

    题目大意: http://www.lydsy.com/JudgeOnline/problem.php?id=2434 题解: 首先我们可以发现这个打字的过程本身就是在Trie上滚来滚去的过程 所以我们 ...

  8. 【HDOJ 5654】 xiaoxin and his watermelon candy(离线+树状数组)

    pid=5654">[HDOJ 5654] xiaoxin and his watermelon candy(离线+树状数组) xiaoxin and his watermelon c ...

  9. POJ 3416 Crossing --离线+树状数组

    题意: 给一些平面上的点,然后给一些查询(x,y),即以(x,y)为原点建立坐标系,一个人拿走第I,III象限的点,另一个人拿II,IV象限的,点不会在任何一个查询的坐标轴上,问每次两人的点数差为多少 ...

随机推荐

  1. 四、Ubuntu 一些常用命令

    1.锁定root用户 :sudo passwd -l root 2.解锁root用户 :sudo passwd -u root 3.切换身份:su root  或者  su 其他用户名,然后输入密码, ...

  2. (7)python tkinter-菜单栏

    菜单栏 Menu f = tkinter.Menu(root) root['menu']=f f.add_command(label='菜单')# f.add_command(label='关于') ...

  3. luogu P1941 飞扬的小鸟

    题目描述 Flappy Bird 是一款风靡一时的休闲手机游戏.玩家需要不断控制点击手机屏幕的频率来调节小鸟的飞行高度,让小鸟顺利通过画面右方的管道缝隙.如果小鸟一不小心撞到了水管或者掉在地上的话,便 ...

  4. luogu P1854 花店橱窗布置

    题目描述 某花店现有F束花,每一束花的品种都不一样,同时至少有同样数量的花瓶,被按顺序摆成一行,花瓶的位置是固定的,从左到右按1到V顺序编号,V是花瓶的数目.花束可以移动,并且每束花用1到F的整数标识 ...

  5. VSCode打开大文件插件

    hexdump for vscode 其实没什么插件,上面的是十六进制文件的插件,对于大文件还是建议用专业的ST或者Notepad++这些.

  6. 3 Suggested Oracle Certifications For Oracle Form's Developers

    The following are the most suggested Oracle Certifications for Oracle Application Developers in Form ...

  7. ScutSDK 0.9版本发布

    ScutSDK简介: ScutSDK是和Scut游戏服务器引擎,简化客户端开发的配套SDK,她彻底打通了Scut开源游戏服务器引擎与客户端引擎(如Cocos2d-x/Quick-x/Unity3D)项 ...

  8. 安全 --- CSRF攻击

    什么是CSRF CSRF(Cross-site request forgery),中文名称:跨站请求伪造,也被称为:one click attack/session riding,缩写为:CSRF/X ...

  9. 【温故知新】——Bootstrap响应式知识点复习

    前言:本文是自己在学习课程中的课程笔记,这里用来温故知新的,并非本人原创. 开发工具 1.记事本,Editplus,... ... 2.Sublime,Dreamweaver 3.Webstorm = ...

  10. JAVA基础针对自己薄弱环节总结01(循环之前的知识)

    java中的标识符 组成:数字.字母.下划线.美元$符号组成.  规则:不能由数字开头.  类名:每一个单词的首字母大写  包名:所有小写  变量名.方法名:第一个单词首字母小写.后面首字母大写  常 ...