QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#745290#9373. Query on TreeJZYZ#WA 0ms16076kbC++145.7kb2024-11-14 08:58:262024-11-14 08:58:26

Judging History

你现在查看的是最新测评结果

  • [2024-11-14 08:58:26]
  • 评测
  • 测评结果:WA
  • 用时:0ms
  • 内存:16076kb
  • [2024-11-14 08:58:26]
  • 提交

answer

// 终于懂了。。。
// 首先就是把所有距离x不超过k的点都加上 v 有两种做法:
// 第一种做法可以参考JOIsc 洒水器一题,可以只做一遍。第二种做法就是把不超过k, 变成k次恰好为 i,需要做k遍,但是可以过
// 我们采用第二种做法
// 首先考虑只有 1, 2 操作该怎么办
// 发现可以求出一个 bfs 序列, 那么同层的点会形成一段区间,然后就是可以暴力从u往父亲跳k次,那么每次修改就是一段区间,复杂度为qklog
// 如果加上3操作呢? 发现这时候一棵子树对应的明显不是一段区间。考虑把这两种序列结合起来
// 我们按照dfs序,依次把每个点对应的k级儿子序列加入,那么序列总长度为n,每个点只有一个k级祖先。
// 然后每个点的子树里到它的距离为d(d <= k) 的点都对应了一段区间 
// 考虑把这样的区间都记录下来, 然后每次修改就好了 
#include<bits/stdc++.h>
#define pb emplace_back
#define MP make_pair
using namespace std;
const int N = 2e5 + 10;
typedef long long LL;
typedef pair< int, int > PII;
int n, q, z;
int L[N][10], R[N][10];
int lt[N], rt[N]; 
int dfn[N], ID[N], dfc, fat[N];
LL a[N];
vector< int > E[N];
struct SegmentTree {
	int l, r; LL tag, mx;
	#define l(x) t[x].l
	#define r(x) t[x].r
	#define tag(x) t[x].tag
	#define mx(x) t[x].mx
}t[N * 4];
void dfs0(int x, int fa) {
	fat[x] = fa;
	for(auto v : E[x]) if(v != fa) dfs0(v, x);
}
void bfs(int rt) { // 按照 bfs 序插入 
	queue< PII > q;
	q.push(MP(rt, 0));
	for(int i = 0; i <= 9; i ++ ) L[rt][i] = 1e9, R[rt][i] = -1e9;
	while(!q.empty()) {
		PII u = q.front(); q.pop();
		int x = u.first, dep = u.second;
		if(!dfn[x]) dfn[x] = ++ dfc, ID[dfc] = x;
		L[rt][dep] = min(L[rt][dep], dfn[x]);
		R[rt][dep] = max(R[rt][dep], dfn[x]);
		if(dep < 9) {
			for(auto v : E[x]) if(v != fat[x]) q.push(MP(v, dep + 1));
		}
	}
}
void dfs1(int x, int fa) {
	bfs(x); lt[x] = L[x][9], rt[x] = R[x][9];
	for(auto v : E[x]) {
		if(v != fa) {
			dfs1(v, x);
	    	lt[x] = min(lt[x], lt[v]);
	     	rt[x] = max(rt[x], rt[v]);
		}
	}
}
void spread(int p) {
	if(tag(p)) {
		mx(p << 1) += tag(p); mx(p << 1 | 1) += tag(p);
		tag(p << 1) += tag(p); tag(p << 1 | 1) += tag(p);
		tag(p) = 0;
	}
}
void update(int p) {
	mx(p) = max(mx(p << 1), mx(p << 1 | 1));
}
void change(int p, int l, int r, LL v) {
	if(l > r) return ;
	if(l <= l(p) && r >= r(p)) {
		tag(p) += v;
		mx(p) += v;
		return ;
	} 
	spread(p);
	int mid = (l(p) + r(p) >> 1);
	if(l <= mid) change(p << 1, l, r, v);
	if(r > mid) change(p << 1 | 1, l, r, v);
	update(p);
}
void build(int p, int l, int r) {
	l(p) = l, r(p) = r;
	if(l == r) {
//		cout << "kkk" << p << ' ' << ID[l] << ' ' << a[ID[l]] << endl;
		mx(p) = a[ID[l]];
		return ;
	}
    int mid = (l + r >> 1);
    build(p << 1, l, mid); build(p << 1 | 1, mid + 1, r);
    update(p);
}
LL ask(int p, int l, int r) {
	if(l > r) return -1e18;
	if(l <= l(p) && r >= r(p)) return mx(p);
	spread(p);
	int mid = (l(p) + r(p) >> 1);
	if(r <= mid) return ask(p << 1, l, r);
	else if(l > mid) return ask(p << 1 | 1, l, r);
	else return max(ask(p << 1, l, r), ask(p << 1 | 1, l, r));
}
LL modify(int x, int k, LL v) { // 把所有与x距离为k的点加上v, 并且求出最大值 
	int now = x, d = k; int lst = -1; LL res = -1e18;
	while(now != 0) {
		if(now == x || d == 0) {
		//	cout << "UUU" << ' ' << now <<' ' << R[now][d] << ' ' << L[now][d] << ' ' << ask(1, L[now][d], R[now][d])<< endl; 
			if(R[now][d] >= L[now][d]) {
				change(1, L[now][d], R[now][d], v);
				res = max(res, ask(1, L[now][d], R[now][d]));	
			}
		}
		else {
			if(R[now][d] >= L[now][d]) {
				change(1, L[now][d], min(R[now][d], L[lst][d - 1] - 1), v);
				res = max(res, ask(1, L[now][d], min(R[now][d], L[lst][d - 1] - 1)));
				if(R[lst][d - 1] > 0) {
					change(1, max(L[now][d], R[lst][d - 1] + 1), R[now][d], v);
		     		res = max(res, ask(1, max(L[now][d], R[lst][d - 1] + 1), R[now][d]));
				}
			}
		}
		lst = now, d --; now = fat[now];
		if(d == -1) break;
	}
	return res;
}
LL Tc(int x, LL v) { // 把 x 的子树加 v 
    LL res = -1e18;
	if(rt[x] >= lt[x]) {
		change(1, lt[x], rt[x], v);
		res = max(res, ask(1, lt[x], rt[x]));
	}
	for(int i = 0; i <= 8; i ++ ) {
		if(L[x][i] <= R[x][i]) {
			change(1, L[x][i], R[x][i], v);
			res = max(res, ask(1, L[x][i], R[x][i]));
		}
	}
	return res;
} 
int main() {
//	freopen("ex_neighbor2.in", "r", stdin);
//	freopen("data.out", "w", stdout);
	scanf("%d%d%d", &n, &q, &z);
	for(int i = 1; i <= n; i ++ ) scanf("%lld", &a[i]);
	for(int i = 1; i < n; i ++ ) {
		int u, v; scanf("%d%d", &u, &v);
		E[u].pb(v); E[v].pb(u);
	}
	dfs0(1, 0);
	dfs1(1, 0); // 按照dfs序插入这个点的9级儿子 
//	cout <<"TTT" <<dfc << endl;
//	for(int i = 1; i <= n; i ++ ) {
//		printf("lt[%d] = %d\n rt[%d] = %d\n", i, lt[i], i, rt[i]);
//	}
//    for(int i = 1; i <= n; i ++ ) {
//    	for(int j = 0; j <= 9; j ++ ) {
//    		if(L[i][j] > n) R[i][j] = n + 1;
//    		printf("L[%d][%d] = %d   R[%d][%d] = %d\n", i, j, L[i][j], i, j, R[i][j]);
//		}
//	}
	build(1, 1, n);
	while(q -- ) {
		int opt, x, k; 
		LL v, res = -1e18;
		scanf("%d", &opt);
		if(opt == 1) {
			scanf("%d%d%lld", &x, &k, &v);
			res = modify(x, k, v);
		}
        else if(opt == 2) {
        	scanf("%d%d%lld", &x, &k, &v);
        	res = -1e18;
        	for(int i = 0; i <= k; i ++ ) {
        		LL vv = modify(x, i, v);
        		res = max(res, vv);
      //  		cout << "HHH" <<i << ' ' << vv << endl;
			}
		}
		else {
			scanf("%d%lld", &x, &v);
			res = Tc(x, v);
		}
		if(res < -3e14) puts("GG");
		else printf("%lld\n", res);
	}
	return 0;
}

Details

Tip: Click on the bar to expand more detailed information

Test #1:

score: 0
Wrong Answer
time: 0ms
memory: 16076kb

input:

1
5 5
1 2 1 3 2
1 2
2 3
2 4
4 5
2 2 1 0
1 2 1 3
3 4 -5
2 5 2 3
3 2 -1

output:

3
5
30
30
33

result:

wrong answer 2nd lines differ - expected: '6', found: '5'