aoj2450 Do use segment tree 树链剖分
2015-10-21 01:42
323 查看
/* *Rainto96 *Beijing University of Posts and Telecommunications School of Software Engineering *http://blog.csdn.net/u011775691 20万个点的树,每个点上有个点权 两种操作 1是将a到b上的所有点权改为c 2是查询a到b路径上最大连续区间和 1直接懒标记 2的话考虑维护从左到右最大和,从右到左最大和 和 最大和并维护 比较麻烦的是从a到b,合并区间的话得按照顺序,a到LCA得反转l,r,LCA到b得反转区间顺序。 */ #include <iostream> #include <cstdio> #include <algorithm> #include <queue> #include <cstring> #include <string> #include <cmath> #include <set> #include <map> #include <vector> #include <climits> using namespace std; #define pb push_back #define ALL(x) x.begin(),x.end() #define VINT vector<int> #define PII pair<int,int> #define MP(x,y) make_pair((x),(y)) #define ll long long #define ull unsigned ll #define MEM0(x) memset(x,0,sizeof(x)) #define MEM(x,val) memset((x),val,sizeof(x)) #define scan(x) scanf("%d",&(x)) #define scan2(x,y) scanf("%d%d",&(x),&(y)) #define scan3(x,y,z) scanf("%d%d%d",&(x),&(y),&(z)) #define scan4(x,y,z,k) scanf("%d%d%d%d",&(x),&(y),&(z),&(k)) #define Max(a,b) a=max(a,b) #define Min(a,b) a=min(a,b) using namespace std; const int INF = 0x3f3f3f3f;/// int n,q; const int MAXN = 200020; int top[MAXN],fa[MAXN] , deep[MAXN] , num[MAXN] , p[MAXN] , fp[MAXN] , son[MAXN],pos , f[MAXN]; struct Edge{ int to,next; }edge[MAXN * 2]; int head[MAXN] , tot; void init(){ tot=0; memset(head, -1, sizeof(head));pos=0;memset(son,-1,sizeof(son)); } void addedge(int u,int v){ edge[tot].to = v; edge[tot].next = head[u];head[u] = tot++; } struct Node{ int l,r,len; int left,right,val,sum; int lazy; }node[MAXN*6]; #define max5(a,b,c,d,e) max(a,max(b,max(c,max(d,e)))) #define lson(x) (x)<<1 #define rson(x) (x)<<1|1 inline Node get(Node& node , Node s1, Node s2){ node.left = max(s1.sum + s2.left , s1.left); node.right = max(s2.sum + s1.right , s2.right); node.val = max5(node.left, node.right, s1.right + s2.left, s1.val , s2.val); node.sum = s1.sum + s2.sum; return node; } struct Seg{ void pushdown(int x){ if(node[x].lazy!=INF){ node[lson(x)].val = node[lson(x)].right = node[lson(x)].left = node[x].lazy > 0 ? node[lson(x)].len*node[x].lazy : node[x].lazy; node[rson(x)].val = node[rson(x)].right = node[rson(x)].left = node[x].lazy > 0 ? node[rson(x)].len*node[x].lazy : node[x].lazy; node[lson(x)].sum = node[lson(x)].len * node[x].lazy; node[rson(x)].sum = node[rson(x)].len * node[x].lazy; node[lson(x)].lazy = node[rson(x)].lazy = node[x].lazy; node[x].lazy = INF; } } void pushup(int x){ get(node[x], node[lson(x)], node[rson(x)]); } void build(int l,int r ,int x=1){ node[x].l = l , node[x].r = r;node[x].left=node[x].right=node[x].val= -INF; node[x].len = r-l+1; node[x].lazy=INF; if(l==r){ node[x].sum = node[x].left = node[x].right = node[x].val = f[ fp[l] ]; return; } int mid = (l+r)/2; build(l,mid,lson(x)); build(mid+1,r,rson(x)); pushup(x); } void update(int l,int r,int val, int x=1){ if(node[x].l>=l && node[x].r<=r){ node[x].val = node[x].left = node[x].right = val > 0?val*node[x].len : val; node[x].sum = node[x].len * val; node[x].lazy = val; return; } int mid = (node[x].l + node[x].r)/2; pushdown(x); if(l <= mid) update(l,r,val,lson(x)); if(r > mid) update(l,r,val,rson(x)); pushup(x); } Node query(int l, int r,int x=1){ if(node[x].l>=l && node[x].r<=r){ //node[x].val = node[x].left = node[x].right = val > 0?val*node[x].len : val; //node[x].sum = node[x].len * val; //node[x].lazy = val; return node[x]; } int mid = (node[x].l + node[x].r)/2; pushdown(x); Node nd;bool has = false; if(l <= mid) { Node tmp = query(l,r,lson(x)); nd = tmp;has =true; } if(r > mid) { Node tmp = query(l,r,rson(x)); if(has) get(nd,nd,tmp); else nd = tmp; } pushup(x); return nd; } }seg; struct TreeLink{ void build(){ dfs1(1,0,0); getpos(1,1); } Node find(int u,int v){ int uid = 0; vector<Node> vc[2]; int f1 = top[u], f2 = top[v]; while(f1 != f2){ if(deep[f1] < deep[f2]){ swap(f1,f2);swap(u,v);uid^=1; } Node tmp =seg.query(p[f1],p[u]); vc[uid].pb(tmp); u = fa[f1]; f1= top[u]; } if(deep[u] > deep[v]) swap(u,v) , uid^=1; vc[uid^1].pb(seg.query(p[u],p[v])); reverse(ALL(vc[uid^1])); for(int i=0;i<vc[uid].size();i++ ) swap(vc[uid][i].left , vc[uid][i].right); if(vc[uid].size() == 0){ Node res = vc[uid^1][0]; for(int i=1;i<vc[uid^1].size();i++){ get(res, res, vc[uid^1][i]); } return res; }else{ Node res = vc[uid][0]; for(int i=1;i<vc[uid].size();i++){ get(res, res , vc[uid][i]); } for(int i=0;i<vc[uid^1].size();i++){ get(res, res,vc[uid^1][i]); } return res; } } void update(int u,int v,int val){ int f1 = top[u] , f2 = top[v]; while(f1 != f2){ if(deep[f1] < deep[f2]) swap(f1,f2),swap(u,v); //cerr<<p[f1]<<" "<<p[u]<<" "<<val<<endl; seg.update(p[f1],p[u],val); u = fa[f1]; f1 = top[u]; } if(deep[u] > deep[v]) swap(u,v); //cerr<<p[u]<<" "<<p[v]<<" "<<val<<endl; seg.update(p[u],p[v],val); } void dfs1(int u,int pre,int d){ deep[u] = d; fa[u] = pre; num[u] = 1; for(int i=head[u];i!=-1;i=edge[i].next){ int v = edge[i].to; if(v!=pre){ dfs1(v,u,d+1); num[u] += num[v]; if(son[u] == -1 || num[v] > num[son[u]]) son[u] = v; } } } void getpos(int u,int sp){ top[u] = sp; if(son[u] != -1) { p[u] = pos++; fp[p[u]] = u; getpos(son[u],sp); }else{ p[u] = pos++; fp[p[u]] = u; return; } for(int i=head[u];i!=-1 ;i =edge[i].next){ int v= edge[i].to; if(v != son[u] && v!=fa[u]) getpos(v,v); } } }trlnk; int e[MAXN][2]; int main(){ #ifndef ONLINE_JUDGE //freopen("C:/OJ/in.txt","r",stdin); #endif while(scan2(n,q)==2){ init(); for(int i=1;i<=n;i++) scan(f[i]); for(int i=0;i<n-1;i++){ scan2(e[i][0],e[i][1]); //cerr<<e[i][0]<<" "<<e[i][1]<<endl; addedge(e[i][0],e[i][1]); addedge(e[i][1],e[i][0]); } trlnk.build(); //cerr<<pos-1<<" pos"<<endl; seg.build(0,pos-1); int kd,a,b,c; while(q--){ scan4(kd,a,b,c); if(kd==1){ trlnk.update(a,b,c); }else{ int res = trlnk.find(a,b).val; printf("%d\n",res); } } } return 0; }
相关文章推荐
- css----零散知识点
- 代理delegate、NSNotification、KVO在开发中的抉择
- Leetcode Maximum Subarray
- 硬盘安装Ubuntu
- 对于给定的一组数据,用weka怎么进行预测?
- 云服务器挂载不了数据盘(急用,求大神解答)好人一生平安
- "openvswitch
- eclipse中运行wordcount任务后在hadoop0.20.2监控页面没有显示该job的问题
- smtp时常要重启才能收发邮件
- leetcode笔记:Longest Common Prefix
- smtp时常要重启才能收发邮件
- smtp时常要重启才能收发邮件
- 深入理解Activity -动手写实例来感受Activity的启动模式
- smtp时常要重启才能收发邮件
- html总结1
- 深入理解Activity -动手写实例来感受Activity的启动模式
- 华为最新桌面云解决方案特性视频来袭(2014年7月揭开神秘面纱^_^)!
- docker里下的centos是一个只读文件系统?我修改/etc/hosts都修改不了,怎么破
- "X5650
- LeetCode OJ 9 Palindrome Number