【BZOJ4999】This Problem Is Too Simple! 离线+树状数组+LCA
【BZOJ4999】This Problem Is Too Simple!
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
题解:由于每种颜色相互独立,可以考虑离线。将修改操作变成一个颜色的删除操作和另一个颜色的加入操作,然后将所有操作和询问都按颜色和时间排序,分别处理每一个颜色。然后我们只需要倍增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的更多相关文章
- HDU 5293 Annoying problem 树形dp dfs序 树状数组 lca
Annoying problem 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5293 Description Coco has a tree, w ...
- HDU 5293 Tree chain problem 树形dp+dfs序+树状数组+LCA
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5293 题意: 给你一些链,每条链都有自己的价值,求不相交不重合的链能够组成的最大价值. 题解: 树形 ...
- 13年山东省赛 Boring Counting(离线树状数组or主席树+二分or划分树+二分)
转载请注明出处: http://www.cnblogs.com/fraud/ ——by fraud 2224: Boring Counting Time Limit: 3 Sec ...
- Educational Codeforces Round 10 D. Nested Segments 离线树状数组 离散化
D. Nested Segments 题目连接: http://www.codeforces.com/contest/652/problem/D Description You are given n ...
- Codeforces Round #365 (Div. 2) D - Mishka and Interesting sum(离线树状数组)
http://codeforces.com/contest/703/problem/D 题意: 给出一行数,有m次查询,每次查询输出区间内出现次数为偶数次的数字的异或和. 思路: 这儿利用一下异或和的 ...
- HDU 4417 离线+树状数组
Super Mario Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total ...
- bzoj 2434: 阿狸的打字机 fail树+离线树状数组
题目大意: http://www.lydsy.com/JudgeOnline/problem.php?id=2434 题解: 首先我们可以发现这个打字的过程本身就是在Trie上滚来滚去的过程 所以我们 ...
- 【HDOJ 5654】 xiaoxin and his watermelon candy(离线+树状数组)
pid=5654">[HDOJ 5654] xiaoxin and his watermelon candy(离线+树状数组) xiaoxin and his watermelon c ...
- POJ 3416 Crossing --离线+树状数组
题意: 给一些平面上的点,然后给一些查询(x,y),即以(x,y)为原点建立坐标系,一个人拿走第I,III象限的点,另一个人拿II,IV象限的,点不会在任何一个查询的坐标轴上,问每次两人的点数差为多少 ...
随机推荐
- ATOM入坑必备插件
Atom作为Javascript/CSS/HTML等前端编辑器利器,其强大功能依靠各种插件,以下是笔者在入坑阶段,精挑细选总结出的必不可少的插件,熟悉运用这些插件,一定成吨提高生产效率.安装这些插件只 ...
- XSY 1749 tree
题目大意 给定一棵基环树, 问你有多少条路径的长度\(\ge K\). 点数\(\le 10^5\) Solution 基环树分治模板题. 我是这样做的: 加边的时候用并查集维护点的连通性, 少加入环 ...
- List与set
1,List与set的区别? List:元素是有序的,元素可以重复,因为集合体系有索引 set:元素是无序的,元素不可以重复,集合体系没有索引 2,list里面特有的方法: 在制定的位置添加元素add ...
- 如何在SQLite中创建自增字段
SQLite 简单的回答:一个声明为 INTEGER PRIMARY KEY 的字段将自动增加. 这里是详细的答案: 从 SQLite 的 2.3.4 版本开始,如果你将一个表中的一个字段声明为 ...
- DotnetBrowser入门教程-(2)启动简单的Web服务
微软的网页服务向来与IIS捆绑紧密,虽然.net core可以脱离iis了,但是基于国内的xp系统,.net core类库的精简,使得我们仍然在dotnetbrowser增加了对web服务的支持. 先 ...
- VS2008中编译通过,但调试时出现“未使用调试信息生成二进制文件”的问题
.只要是“建立项目的时候不应建立空项目,而应当建立一个“win32控制台应用程序”.这样确实可以解决问题.只要你选择的是这个"win32控制台应用程序"则在附加选项里面选不选上“空 ...
- Solidworks拖动装配体的时候物资动力有什么用
Solidworks物资动力就是模拟真实的场景,你在拖动或旋转零件的时候会和周围的零件碰撞,有相互力的作用. 1 标准拖动 2 碰撞检查 3 选择物资动力(零件上面的黑白相间小圆表示物体重心) ...
- HashSet和SortSet对比--c#学习笔记
微软在 .NET 3.5 新增了一个 HashSet 类,在 .NET 4 新增了一个 SortedSet 类. .NET Collection 函数库的 HashSet.SortedSet 这两个泛 ...
- centos下lvs配置
一.lvs-nat模式 网络配置: lvs-server eth0 :host-only adapter 192.168.56.101 lvs-server eth1 :Internal 192.16 ...
- 总结自己使用shell命令行经常使用到的8个小技巧
原创blog,转载请注明出处 Shell是命令解释器 [root@localhost ~]# cat /etc/shells 查看本系统共支持哪些shell 1 tab 命令补全 这个差点儿每次都能用 ...