裸的树连剖分,做成模板写的
ACcode:
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<vector>
#include<set>
#include<map>
#include<queue>
#include<sstream>
#include<string>
#include<bitset>
using namespace std;
typedef long long LL;
const LL LINF = (1LL <<63);
const int INF = 1 << 31;
const int NS = 500010;
const int MS = 19;
const int MOD = 1000000007;
typedef int segValueType;
const int TSIZE = NS;
struct segNode{
int ls, rs; //左右儿子的节点ID
int lid, rid, len; //节点的左右边界及长度
segValueType minv, maxv; //记录子树节点的价值最值
segValueType sumv; //记录子树节点的价值和
segValueType addv; //记录子树节点的增量
bool isLeaf()
{
return (lid == rid);
}
void printData()
{
// cout<<"("<<lid<<","<<rid<<") max = "<<maxv<<" min = "<<minv<<" sum = "<<sumv<<" add = "<<addv<<endl;
printf("(%3d,%3d) max = %3d min = %3d sum = %3d add = %d\n", lid, rid, maxv, minv, sumv, addv);
}
};
struct SegmentTree{
#define lson(x) (x << 1)
#define rson(x) ((x << 1) + 1)
#define pmid(l, r) ((l + r) >> 1)
int maxrt;
segNode wt[TSIZE << 2];
segValueType val[TSIZE];
segValueType cmax(segValueType va, segValueType vb)
{
return (va > vb? va : vb);
}
segValueType cmin(segValueType va, segValueType vb)
{
return (va < vb? va : vb);
}
void PushUpUpdate(int rt)
{
int ls = wt[rt].ls;
int rs = wt[rt].rs;
wt[rt].maxv = cmax(wt[ls].maxv, wt[rs].maxv);
wt[rt].minv = cmin(wt[ls].minv, wt[rs].minv);
wt[rt].sumv = wt[ls].sumv + wt[rs].sumv;
}
void PushDownUpdate(int rt)
{
if(0 != wt[rt].addv)
{
int ls = wt[rt].ls;
int rs = wt[rt].rs;
segValueType addv = wt[rt].addv;
wt[ls].addv += addv;
wt[ls].maxv += addv;
wt[ls].minv += addv;
wt[ls].sumv += wt[ls].len * addv;
wt[rs].addv += addv;
wt[rs].maxv += addv;
wt[rs].minv += addv;
wt[rs].sumv += wt[rs].len * addv;
wt[rt].addv = 0;
}
}
void build(int rt, int l, int r)
{
if(rt > maxrt) maxrt = rt;
// printf("(%d,%d,%d)\n", rt, l, r);
wt[rt].len = r - l + 1;
wt[rt].lid = l;
wt[rt].rid = r;
wt[rt].addv = 0;
if(l == r)
{
wt[rt].ls = -1;
wt[rt].rs = -1;
wt[rt].maxv = wt[rt].minv = val[r];
wt[rt].sumv = val[r];
return ;
}
else
{
wt[rt].ls = lson(rt);
wt[rt].rs = rson(rt);
}
int mid = pmid(wt[rt].lid, wt[rt].rid);
build(lson(rt), l, mid);
build(rson(rt), mid + 1, r);
PushUpUpdate(rt);
}
void update(int rt, int l, int r, int op, segValueType value)
{
if(l <= wt[rt].lid && wt[rt].rid <= r)
{
//如果操作为区间增加val
wt[rt].addv += value;
wt[rt].maxv += value;
wt[rt].minv += value;
wt[rt].sumv += value * wt[rt].len;
return ;
}
if(wt[rt].isLeaf())
{
//正常情况是不会进入此判断的
printf("线段树异常询问:rt = %2d l = %2d r = %2d op = %2d val = %2d\n", rt, l, r, op, value);
return ;
}
PushDownUpdate(rt);
int mid = pmid(wt[rt].lid, wt[rt].rid);
if(l <= mid)
{
update(lson(rt), l, r, op, value);
}
if(r > mid)
{
update(rson(rt), l, r, op, value);
}
PushUpUpdate(rt);
}
segValueType query(int rt, int l, int r, int op)
{
if(l <= wt[rt].lid && wt[rt].rid <= r)
{
segValueType res;
if(1 == op) //查询最大值
{
res = wt[rt].maxv;
}
else if(2 == op) //查询最小值
{
res = wt[rt].minv;
}
else if(3 == op) //查询区间和
{
res = wt[rt].sumv;
}
return res;
}
PushDownUpdate(rt);
int mid = pmid(wt[rt].lid, wt[rt].rid);
segValueType res;
if(l > mid)
{
res = query(rson(rt), l, r, op);
}
else if(r <= mid)
{
res = query(lson(rt), l, r, op);
}
else
{
if(1 == op) //查询最大值
{
res = cmax(query(lson(rt), l, r, op), query(rson(rt), l, r, op));
}
else if(2 == op) //查询最小值
{
res = cmin(query(lson(rt), l, r, op), query(rson(rt), l, r, op));
}
else if(3 == op) //查询区间和
{
res = query(lson(rt), l, r, op) + query(rson(rt), l, r, op);
}
}
return res;
}
void printNode(int rt)
{
printf("rt = %3d", rt);
wt[rt].printData();
}
void printAll()
{
for(int i = 1; i <= maxrt; i++)
{
if(wt[i].lid > 0)
{
printNode(i);
}
}
}
};
const int EDGE_MAX = NS;
struct graphEdge{
int pst;
int next;
int val;
};
struct ForwardStart{
int top;
int head[EDGE_MAX];
graphEdge edge[EDGE_MAX << 1];
void init()
{
top = 0;
memset(head, -1, sizeof(head));
}
//添加一条u->v的边
void addEdge(int u, int v, int val)
{
edge[top].pst = v;
edge[top].val = val;
edge[top].next = head[u];
head[u] = top++;
}
void printAll()
{
printf("top = %d\n", top);
for(int i = 1; i < EDGE_MAX; i++)
{
if(-1 != head[i])
{
printf("head[%2d]'son:%2d", i, edge[head[i]].pst);
for(int j = edge[head[i]].next; j != -1; j = edge[j].next)
{
printf(",%2d", edge[j].pst);
}
puts("");
}
}
}
};
int n, m, q;
struct chainNode{
int fa; //父节点ID
int dep; //节点深度
int scnt; //子树节点总数
int top; //重链第一个节点
int hson; //重儿子ID
int tpos; //节点在线段树中的位置
void init(int _fa, int _dep)
{
fa = _fa;
dep = _dep;
scnt = 1;
hson = -1;
top = -1;
tpos = -1;
}
void printData()
{
printf("fa = %2d dep = %2d scnt = %2d top = %2d hson = %2d tpos = %2d\n", fa, dep, scnt, top, hson, tpos);
}
};
const int CHAIN_MAX = NS;
struct TreeChain{
int val[CHAIN_MAX];
int treeMaxNode;
SegmentTree sTree;
ForwardStart cTree;
chainNode cNode[CHAIN_MAX];
void buildTreeChain()
{
treeMaxNode = 0;
dfsBase(1, -1, 1);
// printAll();
dfsChain(1, -1, 1);
sTree.build(1, 1, treeMaxNode);
// sTree.printAll();
}
void dfsBase(int rt, int fa, int dep)
{
// printf("dfsBase:rt = %3d fa = %3d dep = %3d\n", rt, fa, dep);
cNode[rt].init(fa, dep);
int maxCnt = -1, hson = -1;
for(int i = cTree.head[rt]; i != -1; i = cTree.edge[i].next)
{
int curson = cTree.edge[i].pst;
if(curson == fa) continue;
dfsBase(curson, rt, dep + 1);
cNode[rt].scnt += cNode[curson].scnt;
if(maxCnt < cNode[curson].scnt)
{
maxCnt = cNode[curson].scnt;
hson = curson;
}
}
cNode[rt].hson = hson;
}
void dfsChain(int rt, int fa, int top)
{
// printf("dfsChain:rt = %3d fa = %3d top = %d\n", rt, fa, top);
cNode[rt].top = top;
cNode[rt].tpos = ++treeMaxNode;
sTree.val[treeMaxNode] = val[rt];
int hson = cNode[rt].hson;
if(hson >= 0)
{
dfsChain(hson, rt, top);
}
for(int i = cTree.head[rt]; i != -1; i = cTree.edge[i].next)
{
int curson = cTree.edge[i].pst;
if(curson == fa || hson == curson) continue;
dfsChain(curson, rt, curson);
}
}
void update(int u, int v, int value)
{
// printf("##########tChain.update(%2d, %2d, %2d)", u, v, value);
int topu = cNode[u].top;
int topv = cNode[v].top;
int l, r;
if(topu == topv)
{
l = cNode[u].tpos;
r = cNode[v].tpos;
if(l > r) swap(l, r);
// printf(" a:l = %2d r = %2d\n", l, r);
if(l <= 0)
{
printf("*****(1)树连剖分update异常:u = %d v = %d val = %d\n", u, v, value);
// return ;
}
sTree.update(1, l, r, 1, value);
}
else
{
int nextu = u;
int nextv = v;
int deptopu = cNode[topu].dep;
int deptopv = cNode[topv].dep;
// printf(" topu = %2d(%2d) topv = %2d(%2d)", topu, deptopu, topv, deptopv);
if(deptopu > deptopv)
{
l = cNode[topu].tpos;
r = cNode[u].tpos;
nextu = cNode[topu].fa;
}
else
{
l = cNode[topv].tpos;
r = cNode[v].tpos;
nextv = cNode[topv].fa;
}
sTree.update(1, l, r, 1, value);
if(l <= 0)
{
printf("*****(2)树连剖分update异常:u = %d v = %d val = %d\n", u, v, value);
// return ;
}
// printf(" b:l = %2d r = %2d\n", l, r);
update(nextu, nextv, value);
}
}
int query(int u, int v, int op)
{
// printf("tChain.query(%2d, %2d, %2d)", u, v, op);
int topu = cNode[u].top;
int topv = cNode[v].top;
int l, r;
int ans;
if(topu == topv)
{
l = cNode[u].tpos;
r = cNode[v].tpos;
if(l > r) swap(l, r);
ans = sTree.query(1, l, r, op);
// printf(" l = %2d r = %2d\n", l, r, ans);
}
else
{
int nextu = u;
int nextv = v;
int deptopu = cNode[topu].dep;
int deptopv = cNode[topv].dep;
if(deptopu > deptopv)
{
l = cNode[topu].tpos;
r = cNode[u].tpos;
nextu = cNode[topu].fa;
}
else
{
l = cNode[topv].tpos;
r = cNode[v].tpos;
nextv = cNode[topv].fa;
}
ans = sTree.query(1, l, r, op);
// printf(" l = %2d r = %2d\n", l, r, ans);
ans = max(ans, query(nextu, nextv, op));
}
// printf(" query(%2d, %2d, %2d) = %d\n", u, v, op, ans);
return ans;
}
void printNode(int rt)
{
printf("rt = %2d ", rt);
cNode[rt].printData();
}
void printAll()
{
for(int i = 1; i < CHAIN_MAX; i++)
{
if(cNode[i].scnt > 0)
{
printNode(i);
}
}
}
}tChain;
int main()
{
// freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
while(~scanf("%d %d %d", &n, &m, &q))
{
for(int i = 1; i <= n; i++)
{
scanf("%d", &tChain.val[i]);
}
tChain.cTree.init();
int u, v;
for(int i = 0; i < m; i++)
{
scanf("%d %d", &u, &v);
tChain.cTree.addEdge(u, v, 1);
tChain.cTree.addEdge(v, u, 1);
}
// printf("input compelete!!!\n");
// tChain.cTree.printAll();
tChain.buildTreeChain();
int a,b,c;
char ch[10];
for(int i = 1; i <= q; i++)
{
scanf("%s", ch);
if('I' == ch[0])
{
scanf("%d %d %d", &a, &b, &c);
tChain.update(a, b, c);
}
else if('D' == ch[0])
{
scanf("%d %d %d", &a, &b, &c);
tChain.update(a, b, -c);
}
else
{
scanf("%d", &a);
int ans = tChain.query(a, a, 1);
printf("%d\n", ans);
}
}
}
return 0;
}