您的位置:首页 > 其它

bzoj4999: This Problem Is Too Simple!

2018-01-03 20:58 369 查看
题面在这里

题意:

给一棵树,现在支持以下两种操作:

1. C i x(0<=x<2^31) 表示将i节点的值改为x。

2. Q i j x(0<=x<2^31) 表示询问i节点到j节点的路径上有多少个值为x的节点。

做法:

树链剖分+动态开点线段树。

每个数值都维护一棵线段树。

不想离散可以用map偷懒。。。

代码:

/*************************************************************
Problem: bzoj 4999 This Problem Is Too Simple!
User: fengyuan
Language: C++
Result: Accepted
Time: 5596 ms
Memory: 245664 kb
Submit_Time: 2018-01-03 20:45:26
*************************************************************/

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cctype>
#include<map>
#define mid (l+r>>
4000
;1)
#define lc o<<1
#define rc o<<1|1
using namespace std;
typedef long long LL;

inline LL read()
{
char ch = getchar(); LL x = 0; int op = 1;
for(; !isdigit(ch); ch = getchar()) if(ch == '-') op = -1;
for(; isdigit(ch); ch = getchar()) x = x*10 + ch-'0';
return x*op;
}
inline void writeabs(LL a) { if(a >= 10) writeabs(a/10); putchar(a%10+'0'); }
inline void write(LL a) { if(a < 0) putchar('-'); writeabs(abs(a)); }

const int N = 100010, M = 20000010;
int n, m, total, cnt, clk, all;
int a
, head
, depth
, fa
, sz
, son
, in
, top
;
int rt[N<<2], L[M], R[M], sum[M];
char opt[4];
map<int, int> MP;
struct Edge{
int to, nex;
Edge() {}
Edge(int x, int y) { to = x, nex = y; }
}e[N<<1];

inline int get(int x)
{
if(MP.count(x)) return MP[x];
MP[x] = ++ all; return all;
}
inline void addEdge(int x, int y) { e[++ cnt] = Edge(y, head[x]); head[x] = cnt; }
inline void dfs(int u, int lst, int s)
{
depth[u] = s; fa[u] = lst; sz[u] = 1;
for(int i = head[u]; i; i = e[i].nex){
int v = e[i].to; if(v == lst) continue;
dfs(v, u, s+1); sz[u] += sz[v];
if (sz[v] > sz[son[u]]) son[u] = v;
}
}
inline void dfs2(int u, int t)
{
in[u] = ++ clk; top[u] = t;
if(son[u]) dfs2(son[u], t);
for(int i = head[u]; i; i = e[i].nex)
if(e[i].to != son[u] && e[i].to != fa[u]) dfs2(e[i].to, e[i].to);
}
inline void update(int &o, int l, int r, int x, int y)
{
if(!o) o = ++ total;
if(l == r) { sum[o] += y; return; }
if(x <= mid) update(L[o], l, mid, x, y); else update(R[o], mid+1, r, x, y);
sum[o] = sum[L[o]] + sum[R[o]];
}
inline int getsum(int o, int l, int r, int x, int y)
{
if(!o) return 0;
if(l == x && r == y) return sum[o];
if(y <= mid) return getsum(L[o], l, mid, x, y); else if(x > mid) return getsum(R[o], mid+1, r, x, y);
else return getsum(L[o], l, mid, x, mid) + getsum(R[o], mid+1, r, mid+1, y);
}
inline int qry(int x, int y, int z)
{
int ret = 0;
while(top[x] != top[y]) {
if(depth[top[x]] < depth[top[y]]) swap(x, y);
ret += getsum(rt[z], 1, n, in[top[x]], in[x]);
x = fa[top[x]];
}
if(depth[x] > depth[y]) swap(x, y);
ret += getsum(rt[z], 1, n, in[x], in[y]);
return ret;
}
int main()
{
n = read(), m = read();
for(int i = 1; i <= n; i ++) a[i] = read();
for(int i = 1; i < n; i ++) {
int x = read(), y = read();
addEdge(x, y); addEdge(y, x);
} dfs(1, 0, 0); dfs2(1, 1);
for(int i = 1; i <= n; i ++) {
a[i] = get(a[i]);
update(rt[a[i]], 1, n, in[i], 1);
}
while(m --) {
scanf("%s", opt); int x = read(), y = read(), z;
if(opt[0] == 'C') {
update(rt[a[x]], 1, n, in[x], -1);
a[x] = get(y);
update(rt[a[x]], 1, n, in[x], 1);
} else {
z = read();
if(!MP.count(z)) puts("0"); else write(qry(x, y, MP[z])), puts("");
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: