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. Vim+xxd=强大的十六进制编辑器

    Vim 是黑客文化中强大的编辑器.利用它调用外部十六进制文件显示命令xxd就可以顺利的编辑二进制文件了. 其中,%在vimComandLine时代表当前文件的路径,xxd是以十六进制显示一个文件,xx ...

  2. http-runtime属性

    配置httpRuntime也可以让FileUpload上传更大的文件,不过设置太大了会因用户将大量文件传递到该服务器而导致的拒绝服务攻击(属性有说明) 属性 属性 选项 说明 appRequestQu ...

  3. 洛谷 P2959 [USACO09OCT]悠闲漫步The Leisurely Stroll

    P2959 [USACO09OCT]悠闲漫步The Leisurely Stroll 题目描述 Bessie looks out the barn door at the beautiful spri ...

  4. 实战体验几种MySQLCluster方案

    来源:keepLearning的专栏      http://www.2cto.com/database/201504/387166.html 1.背景 MySQL的cluster方案有很多官方和第三 ...

  5. [转]十五天精通WCF——第九天 高级玩法之自定义Behavior

    终于我又看完了二期爱情保卫战,太酸爽了,推荐链接:http://www.iqiyi.com/a_19rrgublqh.html?vfm=2008_aldbd,不多说,谁看谁入迷,下面言归正传, 看看这 ...

  6. c语言char 和int的问题

    参考:http://www.cnblogs.com/dire/p/5222968.html 参考baidu: char和int的定义我是清楚的,现在有一个问题: 1.设A和B是int型,C是char型 ...

  7. double x = 10 ,y = 0;y = x % 2; 这个表达式正确吗?

    The remainder function and % operator. 以下这段代码过不了编译的(gcc) #include <stdio.h> #include <fenv. ...

  8. Codeforces Round #281 (Div. 2) A. Vasya and Football 暴力

    A. Vasya and Football   Vasya has started watching football games. He has learned that for some foul ...

  9. mysql-5.5 for linux源码安装

    mysql-5.5 for linux源码安装 1.使用Yum安装依赖软件包 # yum install -y gcc gcc-c++ gcc-g77 autoconf automake bison  ...

  10. luogu1415 拆分数列

    题目大意 给出一列数字,需要你添加任意多个逗号将其拆成若干个严格递增的数.如果有多组解,则输出使得最后一个数最小的同时,字典序最大的解(即先要满足最后一个数最小:如果有多组解,则使得第一个数尽量大:如 ...