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输出单独一行表示所求的答案。
 
题解:这个做法,有点牵强吧.
感觉像是空间不够闲着蛋疼才会这么去做.
离线也不是很高级.
对每种颜色建立一个基于 DFS 序的树状数组,权值代表的是一个点出现该颜色的次数.
我们想要查询两点间出现该颜色的次数,只需提取出 DFS 序中对应两点间路径即可.
可是由于空间不够用,只能按照所有颜色分类,依次离线处理一遍.
写起来挺麻烦的......
#include<bits/stdc++.h>
#define setIO(s) freopen(s".in","r",stdin) , freopen(s".out","w",stdout)
#define maxn 300000
using namespace std;
struct OPT
{
int type;
int a,b,c,tag;
OPT(int type=0,int a=0,int b=0,int c=0,int tag=0):type(type),a(a),b(b),c(c),tag(tag){}
}opt[maxn];
vector<OPT>G[maxn];
struct BIT
{
#define N 300000
int C[maxn];
int lowbit(int t)
{
return t & (-t);
}
void update(int x,int delta)
{
while(x<N)
{
C[x]+=delta;
x+=lowbit(x);
}
}
int query(int x)
{
int tmp=0;
while(x>0)
{
tmp+=C[x];
x-=lowbit(x);
}
return tmp;
}
}tree;
char str[10];
int n,Q,edges,tot,tim,mkk=0;
int col[maxn],Arr[maxn],hd[maxn],to[maxn<<1],nex[maxn<<1],dfn[maxn],ln[maxn],st[maxn],ed[maxn];
int siz[maxn],hson[maxn],dep[maxn],top[maxn],fa[maxn],answer[maxn];
void add(int u,int v)
{
nex[++edges]=hd[u],hd[u]=edges,to[edges]=v;
}
void dfs1(int u,int ff)
{
ln[++tim]=u,dfn[u]=st[u]=tim,siz[u]=1,dep[u]=dep[ff]+1,fa[u]=ff;
for(int i=hd[u];i;i=nex[i])
{
int v=to[i];
if(v==ff) continue;
dfs1(v,u);
siz[u]+=siz[v];
if(siz[v]>siz[hson[u]]) hson[u]=v;
}
ed[u]=tim;
}
void dfs2(int u,int tp)
{
top[u]=tp;
if(hson[u]) dfs2(hson[u],tp);
for(int i=hd[u];i;i=nex[i])
{
int v=to[i];
if(v==fa[u]||v==hson[u]) continue;
dfs2(v,v);
}
}
int LCA(int x,int y)
{
while(top[x]^top[y]) dep[top[x]] > dep[top[y]] ? x = fa[top[x]] : y = fa[top[y]];
return dep[x]<dep[y]?x:y;
}
void solve(int cur)
{
for(int i=0,sz=G[cur].size();i<sz;++i)
{
OPT cn=G[cur][i];
switch(cn.type)
{
case -1:
{
int u=cn.a;
tree.update(st[u], -1);
tree.update(ed[u]+1, +1);
break;
}
case 1 :
{
int u=cn.a;
tree.update(st[u], 1);
tree.update(ed[u]+1, -1);
break;
}
case 2 :
{
int u=cn.a;
int v=cn.b;
int c=cn.c;
int g=cn.tag;
int lca = LCA(u,v);
answer[g]=tree.query(dfn[u])+tree.query(dfn[v])-tree.query(dfn[lca])-tree.query(dfn[fa[lca]]);
break;
}
}
}
for(int i=0,sz=G[cur].size();i<sz;++i)
{
OPT cn=G[cur][i];
if(cn.type==-1) tree.update(st[cn.a], +1), tree.update(ed[cn.a]+1,-1);
if(cn.type==1) tree.update(st[cn.a], -1), tree.update(ed[cn.a]+1, +1);
}
}
int main()
{
// setIO("input");
scanf("%d%d",&n,&Q);
for(int i=1;i<=n;++i) scanf("%d",&col[i]),Arr[++tot]=col[i];
for(int i=1;i<n;++i)
{
int x,y;
scanf("%d%d",&x,&y);
add(x,y), add(y,x);
}
dfs1(1,0);
dfs2(1,1);
for(int i=1;i<=Q;++i)
{
scanf("%s",str);
switch(str[0])
{
case 'C' :
{
opt[i].type=1;
scanf("%d%d",&opt[i].a,&opt[i].b);
Arr[++tot]=opt[i].b;
break;
}
case 'Q' :
{
opt[i].type=2;
scanf("%d%d%d",&opt[i].a,&opt[i].b,&opt[i].c);
Arr[++tot]=opt[i].c;
break;
}
}
}
sort(Arr+1,Arr+1+tot);
for(int i=1;i<=Q;++i)
{
if(opt[i].type==1) opt[i].b=lower_bound(Arr+1,Arr+1+tot,opt[i].b)-Arr;
if(opt[i].type==2) opt[i].c=lower_bound(Arr+1,Arr+1+tot,opt[i].c)-Arr;
}
for(int i=1;i<=n;++i)
{
col[i]=lower_bound(Arr+1,Arr+1+tot,col[i])-Arr;
G[col[i]].push_back(OPT(1,i,0,0,0));
}
for(int i=1;i<=Q;++i)
{
if(opt[i].type==2)
{
OPT P=opt[i];
P.tag=++mkk;
G[opt[i].c].push_back(P);
}
else
{
int u=opt[i].a,v=opt[i].b;
G[col[u]].push_back(OPT(-1,u,0,0,0));
G[v].push_back(OPT(1,u,0,0,0));
col[u]=v;
}
}
for(int i=1;i<maxn;++i)
{
if(G[i].size()) solve(i);
}
for(int i=1;i<=mkk;++i)
{
printf("%d\n",answer[i]);
}
return 0;
}

  

BZOJ 4999: This Problem Is Too Simple! DFS序+LCA+树状数组+离线的更多相关文章

  1. POJ 2763 Housewife Wind(DFS序+LCA+树状数组)

    Housewife Wind Time Limit: 4000MS   Memory Limit: 65536K Total Submissions: 11419   Accepted: 3140 D ...

  2. HDU 6203 ping ping ping(dfs序+LCA+树状数组)

    http://acm.hdu.edu.cn/showproblem.php?pid=6203 题意: n+1 个点 n 条边的树(点标号 0 ~ n),有若干个点无法通行,导致 p 组 U V 无法连 ...

  3. HDU 3966 dfs序+LCA+树状数组

    题目意思很明白: 给你一棵有n个节点的树,对树有下列操作: I c1 c2 k 意思是把从c1节点到c2节点路径上的点权值加上k D c1 c2 k 意思是把从c1节点到c2节点路径上的点权值减去k ...

  4. BZOJ 2819: Nim dfs序维护树状数组,倍增

    1.随机选两个堆v,u,询问若在v到u间的路径上的石子堆中玩Nim游戏,是否有必胜策略,如果有,vfleaking将会考虑将这些石子堆作为初始局面之一,用来坑玩家.2.把堆v中的石子数变为k. 分析: ...

  5. BZOJ 1103: [POI2007]大都市meg(dfs序,树状数组)

    本来还想链剖的,结果才发现能直接树状数组的= = 记录遍历到达点与退出点的时间,然后一开始每个到达时间+1,退出时间-1,置为公路就-1,+1,询问直接点1到该点到达时间求和就行了- - CODE: ...

  6. 2018.06.30 BZOJ4765: 普通计算姬(dfs序+分块+树状数组)

    4765: 普通计算姬 Time Limit: 30 Sec Memory Limit: 256 MB Description "奋战三星期,造台计算机".小G响应号召,花了三小时 ...

  7. 【Tyvj2133&BZOJ1146】网络管理Network(树套树,DFS序,树状数组,主席树,树上差分)

    题意:有一棵N个点的树,每个点有一个点权a[i],要求在线实现以下操作: 1:将X号点的点权修改为Y 2:查询X到Y的路径上第K大的点权 n,q<=80000 a[i]<=10^8 思路: ...

  8. 【POJ3321】Apple Tree(DFS序,树状数组)

    题意:给一棵n个节点的树,每个节点开始有一个苹果,m次操作 1.将某个结点的苹果数异或 1 2.查询一棵子树内的苹果数 n,m<=100000   思路:最近一段时间在思考树上统计问题的算法 发 ...

  9. 【BZOJ1103】大都市meg(DFS序,树状数组)

    题意:有一颗树,1号点为根,保证编号小的点深度较小,初始状态每条边都没有被标记,要求实现两个操作在线: A:将连接x,y的边标记 W:查询从1到x的路径上有多少条边未被标记 n<=2*10^5 ...

随机推荐

  1. javascript 使用方式

    第一种:内嵌在html节点中 <html> <body> <input type="button" onclick="document.bo ...

  2. ubuntu 关机命令

    ubuntu 关机命令 关机命令 shutdown ubuntu的终端中默认的是当前用户的命令,只是普通用户,因此在终端器中可以使用sudo -sh 转换到管理员root用户下执行命令. 1)shut ...

  3. multiple web application host under the same website on IIS (authentication mode)

    第一种方式,修改forms的name how to set the forms authentication cookie path assume you have already solved th ...

  4. media type

    https://www.sitepoint.com/mime-types-complete-list/ application/base64 https://github.com/dotnet/doc ...

  5. c programs

  6. PCB MS SQL 行转列(动态拼SQL)

    一.原数据: SELECT inman,indate FROM [fp_db].[dbo].[ppezhpbb] WHERE indate > '2016-5-1' AND indate < ...

  7. Ruby类扩张(extension)

    创建: 2017/09/07 更新: 2017/09/16 修改标题字母大小写 ruby ---> Ruby    扩张类  class 类名     扩张的内容  end           ...

  8. E20170828-mk

    utils  工具类; 效用; 实用工具; 实用菜单; Documentation  n. 记录; 证明某事属实的证据; 参考资料; 文献的编集,文件分类; receive   vt. 收到; 接待; ...

  9. ecshop类的解析1

    前面写了一下我理解的ecshop数据库表,现在看一下我理解的ecshop的类. ecshop类,ECS是一个基础类,它的取得域名的函数我感觉是比较不错的. function get_domain() ...

  10. 《疯狂Python讲义》重要笔记--变量

    一个Python解释器 接下来的旅程——你需要下载好Python,Python解释器通常放在 /usr/local/bin/python3.7 ; 在Unix系统的bash中输入 where pyth ...