POJ3468

来源:互联网 发布:手机蓝牙遥控软件 编辑:程序博客网 时间:2024/05/14 20:07
#include <iostream>#include <cstdio>#include <cstring>using namespace std;#define maxn 100010#define inf 0x3f3f3f3f#define LL long long int#define Key_value ch[ch[root][1]][0]int pre[maxn],key[maxn],ch[maxn][2],root,tot1;int size[maxn],s[maxn],tot2,val[maxn];int add[maxn];LL sum[maxn];int n,q;void NewNode(int & r,int father,int k){if(tot2)r = s[--tot2];else r = ++tot1;pre[r] = father;val[r] = k;sum[r] = k;add[r] = 0;size[r] = 1;ch[r][0] = ch[r][1] = 0;}//将延迟标记更新到孩子结点void PushDown(int r){if(add[r]){val[r] += add[r];add[ch[r][0]] += add[r];add[ch[r][1]] += add[r];sum[ch[r][0]] += (LL)add[r]*size[ch[r][0]];sum[ch[r][1]] += (LL)add[r]*size[ch[r][1]];add[r] = 0;}}//通过孩子结点更新父结点void PushUp(int r){size[r] = size[ch[r][0]] + size[ch[r][1]] + 1;sum[r] = sum[ch[r][0]] + sum[ch[r][1]] + val[r] + add[r];}//旋转,kind为1为右旋,kind为0为左旋void Rotate(int x,int kind){int y = pre[x];PushDown(y);PushDown(x);//类似SBT,要把其中一个分支先给父结点ch[y][!kind] = ch[x][kind];pre[ch[x][kind]] = y;//如果父结点不是根结点,则要和父结点的父结点连接起来if(pre[y])ch[pre[y]][ch[pre[y]][1] == y] = x;pre[x] = pre[y];ch[x][kind] = y;pre[y] = x;PushUp(y);//PushUp(x);}void Splay(int r,int goal){PushDown(r);while(pre[r] != goal){//父结点即是目标位置,goal为0表示,父结点就是根节点if(pre[pre[r]] == goal)Rotate(r,ch[pre[r]][0]==r);else{int y = pre[r];int kind = ch[pre[y]][0] == y;//两个方向不同,则先左旋再右旋if(ch[y][kind] == r){Rotate(r,!kind);Rotate(r,kind);}//两个方向相同,相同方向连续两次else {Rotate(y,kind);Rotate(r,kind);}}}PushUp(r);//更新根节点if(goal == 0)root = r;}//把第k位的数转到goal下边void RotateTo(int k,int goal){int r = root;PushDown(r);while(size[ch[r][0]] != k){if(k < size[ch[r][0]])r = ch[r][0];else {k -= (size[ch[r][0]] + 1);r = ch[r][1];}PushDown(r);}Splay(r,goal);}int Insert(int k){int r = root;while(ch[r][key[r]<k])r = ch[r][key[r] < k];NewNode(ch[r][k>key[r]],r,k);Splay(ch[r][k>key[r]],0);return 1;}//找前驱,即左子树的最右结点int get_pre(int x){int tmp = ch[x][0];if(tmp == 0)return inf;while(ch[tmp][1])tmp = ch[tmp][1];return key[x] - key[tmp];}//找后继,即右子树的最左结点int get_next(int x){int tmp = ch[x][1];if(tmp == 0)return inf;while(ch[tmp][0])tmp = ch[tmp][0];return key[tmp] - key[x];}//查询[l,r]之间的和LL Query(int l,int r){RotateTo(l-1,0);RotateTo(r+1,root);return sum [Key_value];}//更新void Update(int l,int r){int k;scanf("%d",&k);RotateTo(l-1,0);RotateTo(r+1,root);add[Key_value] += k;sum[Key_value] += size[Key_value]*k;}int a[maxn];//建树,中间结点先建立,然后分别对区间两端在左右子树建立void BuildTree(int &x,int l,int r,int father){if(l > r)return;int mid = (l+r)/2;NewNode(x,father,a[mid]);if(l < mid)BuildTree(ch[x][0],l,mid-1,x);if(r > mid)BuildTree(ch[x][1],mid+1,r,x);PushUp(x);}void Init(){for(int i = 0;i < n;i++)scanf("%d",&a[i]);ch[0][0] = ch[0][1] = pre[0] = size[0] = 0;add[0] = sum[0] = 0;root = tot1 = 0;NewNode(root,0,-1);NewNode(ch[root][1],root,-1);size[root] = 2;BuildTree(Key_value,0,n-1,ch[root][1]);//让所有数据夹在两个-1之间PushUp(ch[root][1]);PushUp(root);}int main(){while(scanf("%d%d",&n,&q)!=EOF){Init();while(q--){char str[10];int x,y;scanf("%s%d%d",str,&x,&y);if(str[0] == 'Q')printf("%lld\n",Query(x,y));else Update(x,y);}}return 0;}



风格更新后:

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;#define inf 0x3f3f3f3f#define maxn 100010#define LL long long int#define Key_value ch[ch[root][1]][0]inline int min(int a,int b){return a>b?b:a;}struct SplayTree{int pre[maxn],key[maxn],ch[maxn][2],size[maxn],add[maxn],a[maxn],root,cnt;LL sum[maxn];void init(int n){root = cnt = 0;ch[0][0] = ch[0][1] = pre[0] = size[0] = key[0] = 0;add[0] = sum[0] = 0;NewNode(root,0,-1);NewNode(ch[root][1],root,-1);size[root] = 2;BuildTree(Key_value,0,n-1,ch[root][1]);PushUp(ch[root][1]);PushUp(root);}void BuildTree(int & x,int l,int r,int father){if(l > r)return;int mid = (l+r) >> 1;NewNode(x,father,a[mid]);if(l < mid)BuildTree(ch[x][0],l,mid-1,x);if(r > mid)BuildTree(ch[x][1],mid+1,r,x);PushUp(x);}void NewNode(int & r,int father,int k){r = ++cnt;pre[r] = father;ch[r][0] = ch[r][1] = 0;key[r] = sum[r] = k;add[r] = 0;size[r] = 1;}void PushDown(int r){if(add[r]){key[r] += add[r];add[ch[r][0]] += add[r];add[ch[r][1]] += add[r];sum[ch[r][0]] += (LL)add[r]*size[ch[r][0]];sum[ch[r][1]] += (LL)add[r]*size[ch[r][1]];add[r] = 0;}}void PushUp(int r){size[r] = size[ch[r][0]] + size[ch[r][1]] + 1;sum[r] = sum[ch[r][0]] + sum[ch[r][1]] + key[r] + add[r];}void Rotate(int x,int kind){int y = pre[x];PushDown(y);PushDown(x);ch[y][!kind] = ch[x][kind];pre[ch[x][kind]] = y;if(pre[y])ch[pre[y]][ch[pre[y]][1]==y] = x;pre[x] = pre[y];ch[x][kind] = y;pre[y] = x;PushUp(y);}void Splay(int r,int goal){while(pre[r] != goal){int y = pre[r],z = pre[y];PushDown(z);PushDown(y);PushDown(r);if(pre[pre[r]] == goal){Rotate(r,ch[pre[r]][0]==r);}else {int y = pre[r];int kind = ch[pre[y]][0] == y;if(ch[y][kind] == r){Rotate(r,!kind);}else{Rotate(y,kind);Rotate(r,kind);}}}PushUp(r);if(goal == 0)root = r;}void RotateTo(int k,int goal){int r = root;PushDown(r);while(size[ch[r][0]] != k){if(k < size[ch[r][0]])r = ch[r][0];else{k -= (size[ch[r][0]] + 1);r = ch[r][1];}PushDown(r);}Splay(r,goal);}void Update(int l,int r){int k;scanf("%d",&k);RotateTo(l-1,0);RotateTo(r+1,root);add[Key_value] += k;sum[Key_value] += size[Key_value]*k;}LL Query(int l,int r){RotateTo(l-1,0);RotateTo(r+1,root);return sum[Key_value];}void solve(int n,int q){for(int i = 0;i < n;i++){scanf("%d",&a[i]);}init(n);while(q--){char str[10];int x,y;scanf("%s%d%d",str,&x,&y);if(str[0] == 'Q')printf("%lld\n",Query(x,y));else Update(x,y);}}}spt;int main(){int n,q;while(scanf("%d%d",&n,&q)!=EOF){spt.solve(n,q);}return 0;}


0 0
原创粉丝点击