题意:给你一个数列,区间更新和区间询问
解题思路:splay指针版撸的,4700 ms险过
解题代码:
1 // File Name: spoj3468.cpp 2 // Author: darkdream 3 // Created Time: 2014年11月05日 星期三 19时40分26秒 4 5 #include<vector> 6 #include<list> 7 #include<map> 8 #include<set> 9 #include<deque> 10 #include<stack> 11 #include<bitset> 12 #include<algorithm> 13 #include<functional> 14 #include<numeric> 15 #include<utility> 16 #include<sstream> 17 #include<iostream> 18 #include<iomanip> 19 #include<cstdio> 20 #include<cmath> 21 #include<cstdlib> 22 #include<cstring> 23 #include<ctime> 24 #define LL long long 25 #define maxn 100010 26 using namespace std; 27 int num[maxn]; 28 struct Splaynode{ 29 struct node{ 30 struct node *pre,*ch[2]; 31 LL add; 32 LL sum; 33 LL val; 34 LL size; 35 }*root; 36 node *newnode(int c) 37 { 38 node * p = (node*)malloc(sizeof(node)); 39 p->pre = p->ch[0] = p->ch[1] = NULL; 40 p->sum = p->val = c ; 41 p->size = 1 ; 42 p->add = 0 ; 43 return p ; 44 } 45 void push_down(node *x) 46 { 47 //printf("push_down***%lld ",x->val); 48 x->val += x->add; 49 if(x->ch[0] != NULL) 50 { 51 x->ch[0]->sum += x->ch[0]->size * x->add; 52 x->ch[0]->add += x->add; 53 } 54 if(x->ch[1] != NULL) 55 { 56 x->ch[1]->sum += x->ch[1]->size * x->add; 57 x->ch[1]->add += x->add; 58 } 59 x->add = 0 ; 60 } 61 void push_up(node *x) 62 { 63 x->size = 1; 64 x->sum = x->val + x->add; 65 if(x->ch[0] != NULL) 66 { 67 x->size += x->ch[0]->size; 68 x->sum += x->ch[0]->sum; 69 } 70 if(x->ch[1] != NULL) 71 { 72 x->size += x->ch[1]->size; 73 x->sum += x->ch[1]->sum; 74 } 75 } 76 void print(node *x) 77 { 78 if(x == NULL) 79 return; 80 print(x->ch[0]); 81 printf("%lld(%lld) ",x->val,x->sum); 82 print(x->ch[1]); 83 push_up(x); 84 } 85 void build(node *&x ,int l , int r ,node *f) //这里需要传递一个引用 86 { 87 // printf("%d %d ",l,r); 88 if(l > r ) 89 return ; 90 int m = (l + r ) >> 1; 91 x = newnode(num[m]); 92 build(x->ch[0],l,m-1,x); 93 build(x->ch[1],m+1,r,x); 94 x->pre = f ; 95 push_up(x); 96 } 97 void init(int n) 98 { 99 root = NULL; 100 root = newnode(-1); 101 root->ch[1]=newnode(-1); 102 root->ch[1]->pre = root; 103 root->size = 2; 104 for(int i = 1;i <= n;i ++) 105 scanf("%d",&num[i]); 106 build(root->ch[1]->ch[0],1,n,root->ch[1]); 107 push_up(root->ch[1]); 108 push_up(root); 109 } 110 void Rotate(node *x ,int c) 111 { 112 node *y = x->pre; 113 //printf("%lld %lld ",y->val,x->val); 114 push_down(y); 115 push_down(x); 116 y->ch[!c] = x->ch[c]; 117 if(x->ch[c] != NULL) x->ch[c]->pre = y; 118 x->pre = y->pre; 119 if(y->pre != NULL) 120 { 121 if(y->pre->ch[0] == y) y->pre->ch[0] = x ; 122 else y->pre->ch[1] = x ; 123 } 124 x->ch[c] = y,y->pre = x; 125 push_up(y); 126 } 127 void Delete(node *x) 128 { 129 if(x == NULL) 130 return; 131 Delete(x->ch[0]); 132 Delete(x->ch[1]); 133 //printf("%lld ",x->val); 134 free(x); 135 x = NULL; 136 if(x != NULL) 137 printf("**** "); 138 //x = NULL; 139 //printf("%lld ",x->val); 140 } 141 void Splay(node *x ,node *f) 142 { 143 //printf("**** "); 144 push_down(x); //为何要push_down 145 // printf("**** "); 146 for(; x->pre != f ;) 147 if(x ->pre->pre == f) 148 { 149 if(x->pre-> ch[0] == x) 150 Rotate(x,1); 151 else Rotate(x,0); 152 }else{ 153 node *y = x->pre ,*z = y ->pre; 154 if(z->ch[0] == y) 155 { 156 if(y->ch[0] == x) 157 Rotate(y,1),Rotate(x,1); 158 else Rotate(x,0),Rotate(x,1); 159 }else{ 160 if(y->ch[1] == x) 161 Rotate(y,0),Rotate(x,0); 162 else 163 Rotate(x,1),Rotate(x,0); 164 } 165 } 166 push_up(x); 167 if(f == NULL) root = x; 168 } 169 void Rotateto(int k ,node *goal) 170 { 171 node *x = root; 172 push_down(x); 173 while(1) 174 { 175 if((x->ch[0] == NULL &&k == 0) || (x->ch[0]!= NULL && x->ch[0]->size == k)) 176 break; 177 if(x->ch[0] !=NULL && k < x->ch[0]->size) 178 { 179 x = x->ch[0]; 180 }else{ 181 k -= ((!x->ch[0])?1:x->ch[0]->size+1); 182 x = x->ch[1]; 183 } 184 push_down(x); 185 // printf("%lld %lld %d ",x->val,x->size,k); 186 } 187 // printf("**** "); 188 //printf("%lld ",x->pre->val); 189 Splay(x,goal); 190 } 191 void update() 192 { 193 int l , r, c; 194 scanf("%d %d %d",&l,&r,&c); 195 Rotateto(l-1,NULL); 196 Rotateto(r+1,root); 197 root->ch[1]->ch[0]->add += c; 198 root->ch[1]->ch[0]->sum += root->ch[1]->ch[0]->size * c; 199 } 200 void query() 201 { 202 int l , r; 203 scanf("%d %d",&l,&r); 204 Rotateto(l-1,NULL); 205 // print(root); 206 // printf(" "); 207 Rotateto(r+1,root); 208 // print(root); 209 // printf(" "); 210 // printf("**** "); 211 printf("%lld ",root->ch[1]->ch[0]->sum); 212 } 213 214 }sp; 215 216 int main(){ 217 int n ,m; 218 scanf("%d %d",&n,&m); 219 sp.init(n); 220 //sp.print(sp.root);; 221 // printf(" "); 222 while(m--) 223 { 224 char op[10]; 225 scanf("%s",op); 226 if(op[0] == 'Q') 227 { 228 sp.query(); 229 }else { 230 sp.update(); 231 } 232 } 233 // while() 234 return 0; 235 }
常数大概是线段树的3-4倍
又用数组写了一发
1 // File Name: poj3468.sz.cpp 2 // Author: darkdream 3 // Created Time: 2014年11月07日 星期五 08时45分48秒 4 5 #include<vector> 6 #include<list> 7 #include<map> 8 #include<set> 9 #include<deque> 10 #include<stack> 11 #include<bitset> 12 #include<algorithm> 13 #include<functional> 14 #include<numeric> 15 #include<utility> 16 #include<sstream> 17 #include<iostream> 18 #include<iomanip> 19 #include<cstdio> 20 #include<cmath> 21 #include<cstdlib> 22 #include<cstring> 23 #include<ctime> 24 #define LL long long 25 #define maxn 100010 26 using namespace std; 27 #define keytree ch[ch[root][1]][0] 28 struct SplayTree{ 29 int sz[maxn]; //大小 30 int ch[maxn][2]; //儿子 31 int pre[maxn]; //父亲 32 int root ,top1,top2; 33 int ss[maxn],que[maxn]; 34 inline void Rotate(int x ,int f){ 35 int y = pre[x]; 36 push_down(y); 37 push_down(x); 38 ch[y][!f] = ch[x][f]; 39 pre[ch[x][f]] = y ; 40 pre[x] = pre[y]; 41 if(pre[x]) 42 ch[pre[y]][ch[pre[y]][1] == y] = x; 43 ch[x][f] = y ; 44 pre[y] = x; 45 push_up(y); 46 } 47 void Splay(int x, int goal){ 48 push_down(x); 49 while(pre[x] != goal){ 50 if(pre[pre[x]] == goal){ 51 Rotate(x,ch[pre[x]][0] == x); 52 }else{ 53 int y = pre[x],z = pre[y]; 54 int f = (ch[z][0] == y); 55 if(ch[y][f] == x) 56 { 57 Rotate(x,!f),Rotate(x,f); 58 }else{ 59 Rotate(y,f),Rotate(x,f); 60 } 61 } 62 } 63 push_up(x); 64 if(goal == 0 ) root = x; 65 } 66 void Rotateto(int k ,int goal) 67 { 68 int x = root; 69 push_down(x); 70 while(sz[ch[x][0]] != k){ 71 if(k < sz[ch[x][0]]) 72 { 73 x= ch[x][0]; 74 }else { 75 k -=(sz[ch[x][0]]+1); 76 x = ch[x][1]; 77 } 78 push_down(x); 79 } 80 Splay(x,goal); 81 } 82 /*void erase(int x ){ 83 int father = pre[x]; 84 int head = 0 , tail = 0 ; 85 for() 86 }*/ 87 void debug(){printf("%d ",root);Treaval(root);} 88 void Treaval(int x) { 89 if(x) { 90 Treaval(ch[x][0]); 91 printf("结点%2d:左儿子 %2d 右儿子 %2d 父结点 %2d size = %2d ,val = %2d sum = %3lld ",x,ch[x][0],ch[x][1],pre[x],sz[x],val[x],sum[x]); 92 Treaval(ch[x][1]); 93 } 94 } 95 void newnode(int &x,int c) 96 { 97 if(top2) x= ss[--top2]; 98 else x = ++ top1; 99 ch[x][0] = ch[x][1] = pre[x] = 0 ; 100 sz[x] = 1; 101 102 val[x] = sum[x] = c; 103 add[x] = 0 ; 104 } 105 void push_down(int x){ 106 if(add[x]){ 107 val[x] += add[x]; 108 add[ch[x][0]] += add[x]; 109 add[ch[x][1]] += add[x]; 110 sum[ch[x][0]] += (long long)sz[ch[x][0]] * add[x]; 111 sum[ch[x][1]] += (long long)sz[ch[x][1]] * add[x]; 112 add[x] = 0 ; 113 } 114 } 115 void push_up(int x){ 116 sz[x] = 1 + sz[ch[x][0]] +sz[ch[x][1]]; 117 118 sum[x] = add[x] + val[x] + sum[ch[x][0]] + sum[ch[x][1]]; 119 } 120 void build(int &x,int l ,int r,int f) 121 { 122 if(l > r ) return; 123 int m = (l + r) >> 1; 124 newnode(x,num[m]); 125 build(ch[x][0],l,m-1,x); 126 build(ch[x][1],m+1,r,x); //这里与线段树不同,因为这个节点本身就含有信息 127 pre[x] = f; 128 push_up(x); 129 } 130 void init(int n) 131 { 132 ch[0][0] = ch[0][1] = pre[0] = sz[0] =0 ; 133 add[0] = sum[0] =0 ; 134 root = top1 = 0 ; 135 newnode(root,-1); //这里注意 root 是从1 开始的 136 //printf("%d ",top1); 137 138 newnode(ch[root][1],-1); 139 pre[top1] = root ; 140 sz[root] = 2; 141 for(int i = 1;i <= n;i ++) 142 scanf("%d",&num[i]); 143 build(keytree,1,n,ch[root][1]); 144 push_up(ch[root][1]); 145 push_up(root); 146 } 147 void update() 148 { 149 int l , r, c; 150 scanf("%d %d %d",&l,&r,&c); 151 Rotateto(l-1,0); 152 Rotateto(r+1,root); 153 add[keytree] += c ; 154 sum[keytree] += (long long)sz[keytree] * c; 155 } 156 void query() 157 { 158 int l , r; 159 scanf("%d %d",&l,&r); 160 Rotateto(l-1,0); 161 Rotateto(r+1,root); 162 printf("%lld ",sum[keytree]); 163 } 164 int num[maxn]; 165 int val[maxn]; 166 int add[maxn]; 167 long long sum[maxn]; 168 }sp; 169 int main(){ 170 int n , m ; 171 scanf("%d %d",&n,&m); 172 sp.init(n); 173 while(m--) 174 { 175 char op[10]; 176 scanf("%s",op); 177 if(op[0] == 'Q') 178 { 179 sp.query(); 180 }else { 181 sp.update(); 182 } 183 //sp.debug(); 184 } 185 return 0; 186 }