【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. NGINX配置获取CloudFlare 下的访客真实IP并记录到日志

    我用的是lnmp.org的环境 /usr/local/nginx/conf/nginx.conf 在 http { } 部分增加 map $HTTP_CF_CONNECTING_IP $clientR ...

  2. java 修改字体大小

    在Windows->Preferences->General->Appearance->Colors and Fonts->Java->Java Editor Te ...

  3. AC日记——[国家集训队2010]小Z的袜子 cogs 1775

    [国家集训队2010]小Z的袜子 思路: 传说中的莫队算法(优雅的暴力): 莫队算法是一个离线的区间询问算法: 如果我们知道[l,r], 那么,我们就能O(1)的时间求出(l-1,r),(l+1,r) ...

  4. 51nod 1105 第K大的数 【双重二分/二分套二分/两数组任意乘积后第K大数】

    1105 第K大的数  基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题  收藏  关注 数组A和数组B,里面都有n个整数.数组C共有n^2个整数,分别是A[0] * ...

  5. SQLite to Asp.net Entity Framework 部署问题

    最近做了一个小应用,使用SQLite做数据库.开始用DBLINQ的时候,做一个LINQ查询出现不支持的问题.后来看到Entity Framework是可以支持SQLite的,于是很快转换过来.完成开发 ...

  6. Enter Query Mode Search Tricks Using Enter_Query Built-in in Oracle Forms

    In this post you will learn how to specify any condition in enter query mode of Oracle Forms. Whenev ...

  7. 12.【nuxt起步】-接口请求重构

    用store把api数据交互部分重构出来,让前端更轻一点 新建 /store/gettter.js /store/actions.js /server/config/index.js Index.js ...

  8. 立体3D方式 【转】

    目前为止,至少有四种普遍使用的立体3D传输格式,分别称为frame sequential(帧连续),frame packing(帧封装),side-by-side(并排),以及checkerboard ...

  9. windows 控制台cmd乱码的解决办法

    windows 控制台cmd乱码的解决办法 我本机的系统环境: OS Name: Microsoft Windows 10 企业版 OS Version: 10.0.14393 N/A Build 1 ...

  10. 【Salvation】—— 项目策划&市场分析

    写在前面:这个项目是2017年,我们评选校级创新基金项目的参加作品,小组4人,我为负责人,这个项目现在已经基本完成,目前处于后期收尾阶段. 一.项目的目标.内容及创新之处 1.研究目标 体现人类与自然 ...