題目鏈接:
http://www.tsinsen.com/A1233
題目大意:
給定一棵樹,每個結點有一個權值,你要支持兩個操作:
1.改變某個結點的權值
2.求一個從u開始的路徑使路徑上的每個點的權值之和最大,輸出這個權值和。
這道題目給了3種不同的數據:
第一種是小數據,直接暴力搜索就可以了。
第二種是在鏈上,所以我們求出到每個點的前綴和,然後對前綴和維護最大值和最小值的線段樹,然後每次詢問的答案就是:
ans (p) = max { p - min(1~p-1), max(p+1~n)-p }
於是就過了
第三種數據是在樹上,但數的深度不超過40
於是我們將第二種數據的算法推廣到樹上即可:
我們將每個點的權值設爲其到根結點的權值和,然後按dfs序建立線段樹
對於每次詢問,我們先在其子樹中尋找前綴和最大的,減去其父節點的前綴和。
然後處理子樹外的路徑,我們逐步向根節點推進,然後在當前結點的子樹除了我們推過來的那個子樹以外的點中找最大值,作比較就可以了。具體的實現可以看我的代碼。
值得注意的是這道題的輸入輸出,由於OJ都是標準輸入輸出的,而且是不可能訪問除輸入文件以外的文件,所以他給的函數必然不是用來倒文件的。那麼我們的輸入就要用他給的函數來推出我們需要的信息。
還有我們要注意一下一些細節,比如線段樹的邊界之類的。
附上AC代碼:
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
const int MAXN = 200000;
const int MAXM = 400000;
const int INT_MIN = -2147483648;
char type;
int N, M, L, now, A, B, Q, tmp, i;
int n;
int img[MAXN];
class Edge
{
public:
int to;
int next;
};
Edge es[MAXM];
int et = -1;
int head[MAXN];
void addEdge(int u, int v)
{
et++;
es[et].to = v;
es[et].next = head[u];
head[u] = et;
et++;
es[et].to = u;
es[et].next = head[v];
head[v] = et;
}
void Uncompress(FILE *infile/*, FILE *outfile*/)
{
type = getc(infile);
fscanf(infile, "%d%d%d", &N, &M, &L);
fscanf(infile, "%d%d%d%d", &now, &A, &B, &Q);
//fprintf(outfile, "%c %d\n", type, N);
n = N;
for (i = 1; i <= N; i ++)
{
now = (now * A + B) % Q, tmp = now % 10000;
now = (now * A + B) % Q;
if (now * 2 < Q) tmp *= -1;
/*if (i < N)
fprintf(outfile, "%d ", tmp);
else
fprintf(outfile, "%d\n", tmp);*/
img[i] = tmp;
}
for (i = 1; i < N; i ++)
{
now = (now * A + B) % Q;
tmp = (i < L) ? i : L;
//fprintf(outfile, "%d %d\n", i - now % tmp, i + 1);
addEdge(i - now % tmp, i + 1);
}
}
int w1dfs(int rt, int fr)
{
int ret = img[rt];
for (int i = head[rt]; i != -1; i = es[i].next) {
if (es[i].to == fr)
continue;
ret = max(ret, img[rt] + w1dfs(es[i].to, rt));
}
return ret;
}
void work1()
{
for (i = 1; i < M; i ++)
{
now = (now * A + B) % Q;
if (now * 3 < Q)
{
now = (now * A + B) % Q;
//fprintf(outfile, "Query %d\n", now % N + 1);
printf("%d\n", w1dfs(now % N + 1, 0));
}
else
{
now = (now * A + B) % Q, tmp = now % 10000;
now = (now * A + B) % Q;
if (now * 2 < Q) tmp *= -1;
now = (now * A + B) % Q;
//fprintf(outfile, "Change %d %d\n", now % N + 1, tmp);
img[now % N + 1] = tmp;
}
}
//fprintf(outfile, "Done\n");
}
int mi[300000];
int ma[300000];
int lazy[300000];
#define lc rt<<1, l, mid
#define rc rt<<1|1, mid+1, r
void pushUp(int rt)
{
mi[rt] = min(mi[rt<<1], mi[rt<<1|1]);
ma[rt] = max(ma[rt<<1], ma[rt<<1|1]);
}
void build(int rt, int l, int r)
{
if (l == r) {
ma[rt] = mi[rt] = img[l];
return;
}
int mid = (l+r)>>1;
build(lc);
build(rc);
pushUp(rt);
}
void pushDown(int rt)
{
mi[rt<<1] += lazy[rt];
ma[rt<<1] += lazy[rt];
mi[rt<<1|1] += lazy[rt];
ma[rt<<1|1] += lazy[rt];
lazy[rt<<1] += lazy[rt];
lazy[rt<<1|1] += lazy[rt];
lazy[rt] = 0;
}
void update(int L, int R, int v, int rt, int l, int r)
{
if (L <= l && R>= r) {
ma[rt] += v;
mi[rt] += v;
lazy[rt] += v;
return;
}
if (lazy[rt])
pushDown(rt);
int mid = (l+r)>>1;
if (L <= mid)
update(L, R, v, lc);
if (R > mid)
update(L, R, v, rc);
pushUp(rt);
}
int query(int pos, int rt, int l, int r)
{
if (pos < l)
return 0;
if (l == r) {
return mi[rt];
}
if (lazy[rt])
pushDown(rt);
int mid = (l+r)>>1;
int ret = 2147483647;
if (pos <= mid)
return query(pos, lc);
else
return query(pos, rc);
}
int querymi(int L, int R, int rt, int l, int r)
{
if (R < L || L < 1)
return 0;
if (L <= l && r <= R) {
return mi[rt];
}
if (lazy[rt])
pushDown(rt);
int mid = (l+r)>>1;
int ret = 2147483647;
if (L <= mid)
ret = min(querymi(L, R, lc), ret);
if (R > mid)
ret = min(querymi(L, R, rc), ret);
return ret;
}
int queryma(int L, int R, int rt, int l, int r)
{
if (L > r)
return 0;
if (L <= l && r <= R) {
return ma[rt];
}
if (lazy[rt])
pushDown(rt);
int mid = (l+r)>>1;
int ret = -2147483648;
if (L <= mid)
ret = max(queryma(L, R, lc), ret);
if (R > mid)
ret = max(queryma(L, R, rc), ret);
return ret;
}
void work2()
{
for (i = 2; i <= n; i++)
img[i] += img[i-1];
build(1, 1, n);
for (i = 1; i < M; i ++)
{
now = (now * A + B) % Q;
if (now * 3 < Q)
{
now = (now * A + B) % Q;
//fprintf(outfile, "Query %d\n", now % N + 1);
//printf("%d\n", max(tol[now % N + 1], tor[now % N + 1]));
int k = now % N + 1;
int ans = max(query(k, 1, 1, n) - min(querymi(1, k-1, 1, 1, n), 0),
queryma(k, n, 1, 1, n) - query(k-1, 1, 1, n));
printf("%d\n", ans);
}
else
{
now = (now * A + B) % Q, tmp = now % 10000;
now = (now * A + B) % Q;
if (now * 2 < Q) tmp *= -1;
now = (now * A + B) % Q;
//fprintf(outfile, "Change %d %d\n", now % N + 1, tmp);
int k = query(now % N + 1, 1, 1, n) - query(now % N, 1, 1, n);
update(now % N + 1, n, tmp-k, 1, 1, n);
}
}
//fprintf(outfile, "Done\n");
}
int fa[MAXN];
int dfn[MAXN];
int dff[MAXN];
int imgcpy[MAXN];
int tot = -1;
int relink[MAXN];
void w3dfs(int rt)
{
tot++;
dfn[rt] = tot;
relink[tot] = rt;
for (int i = head[rt]; i != -1; i = es[i].next) {
if (es[i].to == fa[rt])
continue;
fa[es[i].to] = rt;
img[es[i].to] += img[rt];
w3dfs(es[i].to);
}
dff[rt] = tot;
}
void work3()
{
memset(fa, 0, sizeof(fa));
fa[1] = 0;
fa[0] = -1;
img[0] = 0;
addEdge(0, 1);
w3dfs(0);
for (i = 1; i <= n; i++)
imgcpy[i] = img[relink[i]];
memcpy(img, imgcpy, sizeof(img));
build(1, 1, n);
for (i = 1; i < M; i ++)
{
now = (now * A + B) % Q;
if (now * 3 < Q)
{
now = (now * A + B) % Q;
//fprintf(outfile, "Query %d\n", now % N + 1);
int k = now % N + 1;
int ans = queryma(dfn[k], dff[k], 1, 1, n) - query(dfn[fa[k]], 1, 1, n);
int beg = query(dfn[k], 1, 1, n);
while (k > 1) {
int ret = INT_MIN;
if (dfn[k] >= dfn[fa[k]]+1)
ret = max(ret, queryma(dfn[fa[k]], dfn[k]-1, 1, 1, n));
if (dff[k] <= dff[fa[k]]-1)
ret = max(ret, queryma(dff[k]+1, dff[fa[k]], 1, 1, n));
ans = max(ans, ret + beg - query(dfn[fa[fa[k]]], 1, 1, n)
- query(dfn[fa[k]], 1, 1, n));
k = fa[k];
}
printf("%d\n", ans);
}
else
{
now = (now * A + B) % Q, tmp = now % 10000;
now = (now * A + B) % Q;
if (now * 2 < Q) tmp *= -1;
now = (now * A + B) % Q;
//fprintf(outfile, "Change %d %d\n", now % N + 1, tmp);
int k = now % N + 1;
int delta = tmp - (query(dfn[k], 1, 1, n) - query(dfn[fa[k]], 1, 1, n));
update(dfn[k], dff[k], delta, 1, 1, n);
}
}
//fprintf(outfile, "Done\n");
}
void inwork1()
{
char str[10];
int x, y;
while (true)
{
scanf("%s", str);
if (str[0] == 'D')
return;
if (str[0] == 'Q')
{
scanf("%d", &x);
printf("%d\n", w1dfs(x, 0));
}
else
{
scanf("%d %d", &x, &y);
img[x] = y;
}
}
//fprintf(outfile, "Done\n");
}
void inwork2()
{
for (i = 2; i <= n; i++)
img[i] += img[i-1];
char str[10];
build(1, 1, n);
int x, y;
while (true)
{
scanf("%s", str);
if (str[0] == 'D')
return;
if (str[0] == 'Q')
{
scanf("%d", &x);
int ans = max(query(x, 1, 1, n) - min(querymi(1, x-1, 1, 1, n), 0),
queryma(x, n, 1, 1, n) - query(x-1, 1, 1, n));
printf("%d\n", ans);
}
else
{
scanf("%d %d", &x, &y);
int k = query(x, 1, 1, n) - query(x-1, 1, 1, n);
update(x, n, y-k, 1, 1, n);
}
}
//fprintf(outfile, "Done\n");
}
void inwork3()
{
memset(fa, 0, sizeof(fa));
fa[1] = 0;
fa[0] = 0;
img[0] = 0;
addEdge(0, 1);
w3dfs(0);
for (int i = 1; i <= n; i++)
imgcpy[i] = img[relink[i]];
memcpy(img, imgcpy, sizeof(img));
build(1, 1, n);
char str[10];
int x, y;
while (true)
{
scanf("%s", str);
//now = (now * A + B) % Q;
if (str[0] == 'D')
return;
if (str[0] == 'Q')
{
//now = (now * A + B) % Q;
//fprintf(outfile, "Query %d\n", now % N + 1);
//int k = now % N + 1;
int k;
scanf("%d", &k);
int ans = queryma(dfn[k], dff[k], 1, 1, n) - query(dfn[fa[k]], 1, 1, n);
int beg = query(dfn[k], 1, 1, n);
while (k > 1) {
int ret = INT_MIN;
if (dfn[k] >= dfn[fa[k]]+1)
ret = max(ret, queryma(dfn[fa[k]], dfn[k]-1, 1, 1, n));
if (dff[k] <= dff[fa[k]]-1)
ret = max(ret, queryma(dff[k]+1, dff[fa[k]], 1, 1, n));
ans = max(ans, ret + beg - query(dfn[fa[fa[k]]], 1, 1, n)
- query(dfn[fa[k]], 1, 1, n));
k = fa[k];
}
printf("%d\n", ans);
}
else
{
//now = (now * A + B) % Q, tmp = now % 10000;
//now = (now * A + B) % Q;
//if (now * 2 < Q) tmp *= -1;
// now = (now * A + B) % Q;
//fprintf(outfile, "Change %d %d\n", now % N + 1, tmp);
//int k = now % N + 1;
scanf("%d %d", &x, &y);
int delta = y - (query(dfn[x], 1, 1, n) - query(dfn[fa[x]], 1, 1, n));
update(dfn[x], dff[x], delta, 1, 1, n);
}
}
//fprintf(outfile, "Done\n");
}
void readin()
{
scanf("%d", &n);
int x, y;
for (int i = 1; i <= n; i++) {
scanf("%d", &img[i]);
}
for (int i = 1; i < n; i++) {
scanf("%d %d", &x, &y);
addEdge(x, y);
}
}
int main()
{
memset(head, -1, sizeof(head));
#ifdef ONLINE_JUDGE
Uncompress(stdin);
if (type == 'A') {
work1();
return 0;
}
if (type == 'B') {
work2();
return 0;
}
if (type == 'C') {
work3();
return 0;
}
#else
freopen("tra.in", "r", stdin);
type = getchar();
readin();
if (type == 'A') {
inwork1();
return 0;
}
if (type == 'B') {
inwork2();
return 0;
}
if (type == 'C') {
inwork3();
return 0;
}
#endif
return 0;
}