標籤:style blog color os io 資料 for ar
poj3468 裸線段樹。因為在熟悉splay 所以就用splay交了一發。。。開始用的scanf()!==2 居然TLE了。。。然後我就當單組測試資料做的 然後就過了 囧TZ
#include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <cmath>using namespace std;#define rt ch[root][1]#define lrt ch[rt][0]#define ls ch[x][0]#define rs ch[x][1]#define inf 0x3f3f3f3fconst int maxn=100100;int root,top;//root為建立節點時的根節點int ch[maxn][2],f[maxn];long long sz[maxn],num[maxn],val[maxn],sum[maxn],add[maxn];int n,m;//ch[x][0],ch[x][1]:x的左右兒子,f[x]:x的父親節點,val[x]:x的值,sz[x]以x為根的子樹的節點個數inline void pushup(int x){ sz[x]=sz[ls]+sz[rs]+1; sum[x]=sum[ls]+sum[rs]+val[x]; //維護其他資訊}inline void pushdown(int x){ if(add[x]) { val[x]+=add[x]; add[ls]+=add[x]; add[rs]+=add[x]; sum[ls]+=(long long)(sz[ls]*add[x]); sum[rs]+=(long long)(sz[rs]*add[x]); add[x]=0; } //維護其他資訊}inline void link(int y,int x,int d)//把節點y的(左或右)兒子設為x{ f[x]=y; ch[y][d]=x;}inline int is(int x)//判斷x為左兒子0還是右兒子1{ return ch[f[x]][1]==x;}inline void rotate(int x,int d){ int y=f[x]; int z=f[y]; pushdown(y); pushdown(x); link(y,ch[x][d],!d); if(z) link(z,x,is(y)); f[x]=z; link(x,y,d); pushup(y);}inline void zag(int x){ rotate(x,0);}inline void zig(int x){ rotate(x,1);}inline void splay(int x,int goal=0)//第二個元素沒有傳參就預設為0,splay到0即將該節點旋轉到根//將根為r的子樹調整到x的父節點為goal的位置{ pushdown(x); while(f[x]!=goal) { int y=f[x]; int z=f[y]; if(z==goal) { rotate(x,!is(x)); break; } if(ch[z][0]==y) { if(ch[y][0]==x) zig(y),zig(x); else zag(x),zig(x); } else { if(ch[y][1]==x) zag(y),zag(x); else zig(x),zag(x); } } if(goal==0) root=x; pushup(x);}//splay操作一般不做改動inline void newnode(int &x,int father,long long v){ x=++top; f[x]=father; val[x]=v; add[x]=0; ls=rs=0; sz[x]=0; //.....按題意建立資訊}inline bool insert(int v){ int x=root; while(ch[x][val[x]<v]) { if(val[x]==v) { splay(x); return false; } x=ch[x][val[x]<v]; } newnode(ch[x][val[x]<v],x,v); splay(ch[x][val[x]<v]); return true;}inline void build(int &x,int y,int l,int r){ if(l>r) return ; int mid=(l+r)>>1; newnode(x,y,num[mid]); build(ls,x,l,mid-1); build(rs,x,mid+1,r); pushup(x);}inline void init(int n){ root=top=0; ch[0][0]=ch[0][1]=f[0]=val[0]=add[0]=sz[0]=sum[0]=0; newnode(root,0,0); newnode(rt,root,0); sz[root]=2; for(int i=0; i<n; i++) scanf("%lld",&num[i]); build(lrt,rt,0,n-1); pushup(rt); pushup(root); //for(int x=0;x<=top;x++){ // printf("x=%d f[x]=%d ls=%d rs=%d val=%d sum=%d add=%d sz=%d\n",x,f[x],ls,rs,val[x],sum[x],add[x],sz[x]); //}}inline int pre(int x)//獲得前驅,調用時pre(root)即可{ x=ls; if(x==0) return inf; while(rs) x=rs; return val[x];}inline int next(int x)//調用時next(root)即可,後繼{ x=rs; if(x==0) return inf; while(ls) x=ls; return val[x];}inline int get_k(int x,int k)//返回的是第k小的點的標號(從小到大),值要用val來擷取{ pushdown(x); int num=sz[ls]+1; if(num==k) return x; if(k<num) return get_k(ls,k); return get_k(rs,k-num);}inline void update(){ int l,r; long long c; scanf("%d %d %lld",&l,&r,&c); int x=get_k(root,l); splay(x); int y=get_k(root,r+2); splay(y,root); add[lrt]+=c; sum[lrt]+=sz[lrt]*c;}//查詢一段區間的值inline void query(){ int l,r; scanf("%d%d",&l,&r); int x,y; x=get_k(root,l); y=get_k(root,r+2); splay(x); splay(y,root); printf("%lld\n",sum[lrt]);}int main(){ scanf("%d%d",&n,&m); init(n); for(int i=1;i<=m;i++){ int l,r,d; char c; scanf("%c%c",&c,&c); if(c==‘Q‘){ //cout<<c<<endl; query(); } if(c==‘C‘){ update(); } }}