Description
Input
Output
Sample Input
5 6 1 2 3 4 5 Q 1 5 U 3 6 Q 3 4 Q 4 5 U 2 9 Q 1 5
Sample Output
5 6 5 9
Hint
Huge input,the C function scanf() will work better than cin
线段树点更新裸题
//#pragma comment(linker, "/STACK:102400000,102400000" #include<cstdio> #include<cstring> #include<cmath> #include<cstdlib> #include<iostream> #include<algorithm> #include<vector> #include<map> #include<queue> #include<stack> #include<string> #include<map> #include<set> #include<ctime> #define eps 1e-6 #define MAX 200005 #define INF 0x3f3f3f3f #define LL long long #define pii pair<int,int> #define rd(x) scanf("%d",&x) #define rd2(x,y) scanf("%d%d",&x,&y) #define rd3(x,y,z) scanf("%d%d%d",&x,&y,&z) using namespace std; int a[MAX];///存储结点的位置 struct node{ int left,right;///线段区间 int sum;///区间上的人数 }b[MAX*3]; void Build(int left,int right,int i){///建树 b[i].left=left,b[i].right=right; if(left==right){///先用数组存下该队的人 b[i].sum=a[left]; return ; } int mid=(left+right)/2; Build(left,mid,2*i);///递归建立左子树 Build(mid+1,right,2*i+1);///递归建立右子树 b[i].sum=max(b[2*i].sum,b[2*i+1].sum);///记录该结点左右子树的值 } void updata(int j,int num,int i){ ///修改树 自上而下修改 if(b[i].left==b[i].right)///到达叶子结点 b[i].sum=num; else{ j<=b[i*2].right ? updata(j,num,2*i) : updata(j,num,2*i+1); ///递归左子树///建立右子树 b[i].sum=max(b[i<<1].sum,b[i<<1|1].sum); } } int Query(int left,int right,int i){///查询 int mid; if( b[i].left==left && b[i].right==right ) return b[i].sum; mid=(b[i].left+b[i].right)/2; if(right<=mid) return Query(left,right,2*i);///在左子树 else if(left>mid) return Query(left,right,2*i+1);///在右子树 else return max(Query(left,mid,2*i),Query(mid+1,right,2*i+1));///否则在中间,跨越树的两个分支 } int main() { int j,num,n,m,coun=0; char s[10]; while(~scanf("%d%d",&n,&m)){ for(int i=1;i<=n;i++) scanf("%d",&a[i]); Build(1,n,1);///建树 1作为根 for(int i=0;i<m;i++){ scanf("%s",s); ///操作 scanf("%d%d",&j,&num); if(!strcmp(s,"Q")) printf("%d\n",Query(j,num,1)); if(!strcmp(s,"U")) updata(j,num,1);///从根结点开始 } } return 0; }