BZOJ 4127 Abs 树链剖分
2015-06-12 11:11
302 查看
题目大意:给定一棵树,每个点有一个整数权值(可以是负数),要求支持两种操作:
1.链上加
2.链上绝对值之和
由于加的数保证非负,因此一个负数变成一个正数最多有nn次
树链剖分,在线段树中维护一下区间最大负数即可
不知道为何 写了两个线段树就TLE 把两个线段树合并成一个就7s过了
1.链上加
2.链上绝对值之和
由于加的数保证非负,因此一个负数变成一个正数最多有nn次
树链剖分,在线段树中维护一下区间最大负数即可
不知道为何 写了两个线段树就TLE 把两个线段树合并成一个就7s过了
[code]#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define M 100100 using namespace std; struct Segtree{ Segtree *ls,*rs; long long sum,mark; int cnt;//区间中负数的个数 pair<int,int> max_pos; void* operator new (size_t) { static Segtree mempool[M<<1],*C=mempool; return C++; } void Add(int x,int y,long long val) { sum+=(y-x+1-2*cnt)*val; mark+=val; if(max_pos.first!=(signed)0xefefefef) max_pos.first+=val; } void Push_Up(int x,int y) { sum=ls->sum+rs->sum; cnt=ls->cnt+rs->cnt; max_pos=max(ls->max_pos,rs->max_pos); } void Push_Down(int x,int y) { int mid=x+y>>1; if(mark) { ls->Add(x,mid,mark); rs->Add(mid+1,y,mark); mark=0; } } void Build_Tree(int x,int y,int a[]) { int mid=x+y>>1; if(x==y) { if(a[mid]<0) max_pos=pair<int,int>(a[mid],mid),cnt=1; else max_pos=pair<int,int>(0xefefefef,0); sum=abs(a[mid]); return ; } (ls=new Segtree)->Build_Tree(x,mid,a); (rs=new Segtree)->Build_Tree(mid+1,y,a); Push_Up(x,y); } void Reverse(int x,int y,int pos) { int mid=x+y>>1; if(x==y) { cnt=0; sum=-sum; max_pos=pair<int,int>(0xefefefef,0); return ; } Push_Down(x,y); if(pos<=mid) ls->Reverse(x,mid,pos); else rs->Reverse(mid+1,y,pos); Push_Up(x,y); } void Add(int x,int y,int l,int r,long long val) { int mid=x+y>>1; if(x==l&&y==r) { Add(x,y,val); return ; } Push_Down(x,y); if(r<=mid) ls->Add(x,mid,l,r,val); else if(l>mid) rs->Add(mid+1,y,l,r,val); else ls->Add(x,mid,l,mid,val) , rs->Add(mid+1,y,mid+1,r,val) ; Push_Up(x,y); } long long Query(int x,int y,int l,int r) { int mid=x+y>>1; if(x==l&&y==r) return sum; Push_Down(x,y); if(r<=mid) return ls->Query(x,mid,l,r); if(l>mid) return rs->Query(mid+1,y,l,r); return ls->Query(x,mid,l,mid) + rs->Query(mid+1,y,mid+1,r) ; } pair<int,int> Get_Pos(int x,int y,int l,int r) { int mid=x+y>>1; if(x==l&&y==r) return max_pos; Push_Down(x,y); if(r<=mid) return ls->Get_Pos(x,mid,l,r); if(l>mid) return rs->Get_Pos(mid+1,y,l,r); return max( ls->Get_Pos(x,mid,l,mid) , rs->Get_Pos(mid+1,y,mid+1,r) ); } }*tree=new Segtree; struct abcd{ int to,next; }table[M<<1]; int head[M],tot; int n,m,a[M]; int fa[M],son[M],dpt[M],size[M]; int pos[M],top[M],_a[M]; void Add(int x,int y) { table[++tot].to=y; table[tot].next=head[x]; head[x]=tot; } void DFS1(int x) { int i; dpt[x]=dpt[fa[x]]+1; size[x]=1; for(i=head[x];i;i=table[i].next) if(table[i].to!=fa[x]) { fa[table[i].to]=x; DFS1(table[i].to); size[x]+=size[table[i].to]; if(size[table[i].to]>size[son[x]]) son[x]=table[i].to; } } void DFS2(int x) { static int T; int i; _a[pos[x]=++T]=a[x]; if(son[fa[x]]==x) top[x]=top[fa[x]]; else top[x]=x; if(son[x]) DFS2(son[x]); for(i=head[x];i;i=table[i].next) if(table[i].to!=fa[x]&&table[i].to!=son[x]) DFS2(table[i].to); } void Add(int x,int y,int z) { int fx=top[x],fy=top[y]; while(fx!=fy) { if(dpt[fx]<dpt[fy]) swap(fx,fy),swap(x,y); while(1) { pair<int,int> temp=tree->Get_Pos(1,n,pos[fx],pos[x]); if(temp.first+z>=0) tree->Reverse(1,n,temp.second); else break; } tree->Add(1,n,pos[fx],pos[x],z); x=fa[fx];fx=top[x]; } if(dpt[x]<dpt[y]) swap(x,y); while(1) { pair<int,int> temp=tree->Get_Pos(1,n,pos[y],pos[x]); if(temp.first+z>=0) tree->Reverse(1,n,temp.second); else break; } tree->Add(1,n,pos[y],pos[x],z); } long long Query(int x,int y) { int fx=top[x],fy=top[y]; long long re=0; while(fx!=fy) { if(dpt[fx]<dpt[fy]) swap(fx,fy),swap(x,y); re+=tree->Query(1,n,pos[fx],pos[x]); x=fa[fx];fx=top[x]; } if(dpt[x]<dpt[y]) swap(x,y); return re+tree->Query(1,n,pos[y],pos[x]); } int main() { int i,p,x,y,z; cin>>n>>m; for(i=1;i<=n;i++) scanf("%d",&a[i]); for(i=1;i<n;i++) { scanf("%d%d",&x,&y); Add(x,y);Add(y,x); } DFS1(1);DFS2(1); tree->Build_Tree(1,n,_a); for(i=1;i<=m;i++) { scanf("%d%d%d",&p,&x,&y); if(p==1) { scanf("%d",&z); if(z) Add(x,y,z); } else { #ifdef PoPoQQQ printf("%I64d\n",Query(x,y)); #else printf("%lld\n",Query(x,y)); #endif } } return 0; }
相关文章推荐
- Reverse Linked List II
- sar命令详解
- php开发环境(图文) 原地址:http://my.oschina.net/joanfen/blog?catalog=350189
- UA 4255 Guess (拓扑排序)
- Ubuntu下配置支持Windows访问的samba共享
- JavaScript继承详解(二)
- Linux课程总结
- Android开发
- 关于matlab SVM工具箱的问题
- 对指针、数组的总结
- Callable 获取线程返回值
- 一些小方法
- oracle11g使用plsql导出空表
- 20150612工作中的问题总结
- JavaScript中的toUTCString()方法使用详解
- java中的方法重载和方法覆盖
- Java调用QQ快速聊天-调用CMD命令打开网址
- xcode PCL 工程建立及测试
- java 安装数据库驱动
- Android的context浅析