【题意】
N个数,M个操作。Q A B,查询区间[A,B]的最大值;U A B,把点A的值改为B。
【分析】
线段树显然可以秒掉。
splay小练习。
Splay代码
1 /* 2 http://acm.pku.edu.cn/JudgeOnline/problem?id=3468 3 区间跟新,区间求和 4 */ 5 #include <cstdio> 6 #define keyTree (ch[ ch[root][1] ][0]) 7 int max(int x,int y) 8 { 9 return x>y?x:y; 10 } 11 const int maxn = 2002000; 12 struct SplayTree{ 13 int sz[maxn]; 14 int ch[maxn][2]; 15 int pre[maxn]; 16 int root , top1; 17 18 void Rotate(int x,int f) {//f=0:zag, f=1:zig 19 int y = pre[x]; 20 push_down(y); 21 push_down(x); 22 ch[y][!f] = ch[x][f]; 23 pre[ ch[x][f] ] = y; 24 pre[x] = pre[y]; 25 if(pre[x]) ch[ pre[y] ][ ch[pre[y]][1] == y ] = x; 26 ch[x][f] = y; 27 pre[y] = x; 28 push_up(y); 29 } 30 void Splay(int x,int goal) { 31 push_down(x); 32 while(pre[x] != goal) { 33 if(pre[pre[x]] == goal) { 34 Rotate(x , ch[pre[x]][0] == x); 35 } else { 36 int y = pre[x] , z = pre[y]; 37 int f = (ch[z][0] == y); 38 if(ch[y][f] == x) { 39 Rotate(x , !f) , Rotate(x , f);//之字型 40 } else { 41 Rotate(y , f) , Rotate(x , f);//一字型 42 } 43 } 44 } 45 push_up(x); 46 if(goal == 0) root = x; 47 } 48 void RotateTo(int k,int goal) {//把第k位的数转到goal下边 49 int x = root; 50 push_down(x); 51 while(sz[ ch[x][0] ] != k) { 52 if(k < sz[ ch[x][0] ]) { 53 x = ch[x][0]; 54 } else { 55 k -= (sz[ ch[x][0] ] + 1); 56 x = ch[x][1]; 57 } 58 push_down(x); 59 } 60 Splay(x,goal); 61 } 62 //以上一般不修改// 63 void debug() {printf("%d\n",root);Treaval(root);} 64 void Treaval(int x) { 65 if(x) { 66 Treaval(ch[x][0]); 67 printf("结点%2d:左儿子 %2d 右儿子 %2d 父结点 %2d size = %2d ,val = %2d\n",x,ch[x][0],ch[x][1],pre[x],sz[x],val[x]); 68 Treaval(ch[x][1]); 69 } 70 } 71 //以上Debug 72 73 74 //以下是题目的特定函数: 75 void NewNode(int &x,int c) { 76 x = ++top1; 77 ch[x][0] = ch[x][1] = pre[x] = 0; 78 sz[x] = 1; 79 80 val[x] = mmm[x] = c;/*这是题目特定函数*/ 81 } 82 83 //把延迟标记推到孩子 84 void push_down(int x) {/*这是题目特定函数*/ 85 } 86 //把孩子状态更新上来 87 void push_up(int x) { 88 sz[x] = 1 + sz[ ch[x][0] ] + sz[ ch[x][1] ]; 89 /*这是题目特定函数*/ 90 mmm[x] = val[x]; 91 mmm[x] = max(mmm[x], mmm[ch[x][0]]); 92 mmm[x] = max(mmm[x], mmm[ch[x][1]]); 93 } 94 95 /*初始化*/ 96 void makeTree(int &x,int l,int r,int f) { 97 if(l > r) return ; 98 int m = (l + r)>>1; 99 NewNode(x , num[m]); /*num[m]权值改成题目所需的*/ 100 makeTree(ch[x][0] , l , m - 1 , x); 101 makeTree(ch[x][1] , m + 1 , r , x); 102 pre[x] = f; 103 push_up(x); 104 } 105 void init(int n) {/*这是题目特定函数*/ 106 ch[0][0] = ch[0][1] = pre[0] = sz[0] = 0; 107 val[0] = mmm[0] = 0; 108 109 root = top1 = 0; 110 //为了方便处理边界,加两个边界顶点 111 NewNode(root , -1); 112 NewNode(ch[root][1] , -1); 113 pre[top1] = root; 114 sz[root] = 2; 115 for (int i = 0 ; i < n ; i ++) scanf("%d",&num[i]); 116 makeTree(keyTree , 0 , n-1 , ch[root][1]); 117 push_up(ch[root][1]); 118 push_up(root); 119 //Treaval(root); 120 //printf("%d %d %d %d\n",root, sz[root],val[root],mmm[root]); 121 } 122 /*更新*/ 123 void update( ) {/*这是题目特定函数*/ 124 int A, B; 125 scanf("%d%d",&A,&B); 126 RotateTo(A,0); 127 //printf("%d\n",mmm[root]); 128 //add[ keyTree ] += c; 129 val[root] = B; 130 push_up(root); 131 //sum[ keyTree ] += (long long)c * sz[ keyTree ]; 132 } 133 /*询问*/ 134 void query() {/*这是题目特定函数*/ 135 int l , r; 136 scanf("%d%d",&l,&r); 137 RotateTo(l-1 , 0);//root 就是l-1 138 RotateTo(r+1 , root); 139 //Treaval(root); 140 //printf("%d\n",val[root]); 141 printf("%d\n",mmm[keyTree]); 142 } 143 144 145 /*这是题目特定变量*/ 146 int num[maxn]; 147 int val[maxn]; 148 int mmm[maxn]; 149 }spt; 150 151 152 int main() { 153 int n , m; 154 while (scanf("%d%d",&n,&m)==2) 155 { 156 spt.init(n); 157 while(m --) { 158 char op[3]; 159 scanf("%s",op); 160 if(op[0] == 'Q') { 161 spt.query(); 162 } else { 163 spt.update(); 164 } 165 } 166 } 167 return 0; 168 }
线段树代码
1 #include <cstdio> 2 #include <cstdlib> 3 #include <cstring> 4 #include <cmath> 5 #include <ctime> 6 #include <cassert> 7 #include <iostream> 8 #include <sstream> 9 #include <fstream> 10 #include <map> 11 #include <set> 12 #include <vector> 13 #include <queue> 14 #include <algorithm> 15 #define min(x,y) (x<y?x:y) 16 #define max(x,y) (x>y?x:y) 17 #define distance(x1,x2,y1,y2,z1,z2) (sqrt(pow(x2-x1,2)+pow(y2-y1,2)+pow(z2-z1,2))) 18 #define myabs(x) (x<0?-x:x) 19 #define sgn(x) (x<0?-1:(x>0?1:0)) 20 #define clr(list) memset(list,0,sizeof(list)) 21 #define maxn 200050 22 23 using namespace std; 24 25 struct node{ 26 int l,r,m; 27 int score; 28 int maxs; 29 } tree[3*maxn]; 30 int stu[maxn]; 31 32 int N,M; 33 34 int build(int l,int r,int root) 35 { 36 tree[root].l=l; 37 tree[root].r=r; 38 tree[root].m=(r+l)/2; 39 if (l==r) 40 { 41 tree[root].score=stu[l]; 42 tree[root].maxs=stu[l]; 43 return tree[root].maxs; 44 } 45 int max_l=build(l,(l+r)/2,root*2); 46 int max_r=build((l+r)/2+1,r,root*2+1); 47 tree[root].maxs=max(max_l,max_r); 48 return tree[root].maxs; 49 } 50 void update(int x, int root ,int y) 51 { 52 if (tree[root].l==tree[root].r) 53 { 54 tree[root].score=y; 55 tree[root].maxs=y; 56 return ; 57 } 58 if (y>tree[root].maxs) 59 tree[root].maxs=y; 60 if (x<=tree[root].m) 61 update(x,2*root,y); 62 else 63 update(x,2*root+1,y); 64 return ; 65 } 66 int search(int l,int r,int root) 67 { 68 if (l<=tree[root].l && r>=tree[root].r) 69 return tree[root].maxs; 70 int max_l=0; 71 int max_r=0; 72 if (l<=tree[root].m) 73 max_l=search(l,r,2*root); 74 if (r>tree[root].m) 75 max_r=search(l,r,2*root+1); 76 return max_l>max_r?max_l:max_r; 77 } 78 int main() 79 { 80 while (scanf("%d%d",&N,&M)==2) 81 { 82 for (int i=1;i<=N;i++) 83 scanf("%d",&stu[i]); 84 build(1,N,1); 85 for (int i=1;i<=M;i++) 86 { 87 char ch[5]; 88 int x,y; 89 scanf("%s%d%d",ch,&x,&y); 90 if (ch[0]=='U') 91 update(x,1,y); 92 else 93 { 94 if (x>y) 95 swap(x,y); 96 printf("%d\n",search(x,y,1)); 97 } 98 } 99 } 100 return 0; 101 }