主要是修改区间的时候要维护线段数。。
A Simple Problem with Integers
Time Limit: 5000MS | Memory Limit: 131072K | |
Total Submissions: 31920 | Accepted: 9071 | |
Case Time Limit: 2000MS |
Description
You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type of operation is to add some given number to each number in a given interval. The other is to ask for the sum of numbers in a given interval.
Input
The first line contains two numbers N and Q. 1 ≤ N,Q ≤ 100000.
The second line contains N numbers, the initial values of A1, A2, ... , AN. -1000000000 ≤ Ai ≤ 1000000000.
Each of the next Q lines represents an operation.
"C a b c" means adding c to each of Aa, Aa+1, ... , Ab. -10000 ≤ c ≤ 10000.
"Q a b" means querying the sum of Aa, Aa+1, ... , Ab.
Output
You need to answer all Q commands in order. One answer in a line.
Sample Input
10 5 1 2 3 4 5 6 7 8 9 10 Q 4 4 Q 1 10 Q 2 4 C 3 6 3 Q 2 4
Sample Output
4 55 9 15
#include<iostream> #include<fstream> using namespace std; struct e{ int left,right; long long add; long long sum; }; e tree[400011]; long long a[100001]; long long build(int s,int t,int num){ //建树 long long i,j; tree[num].left=s; tree[num].right=t; tree[num].add=0; if(s!=t) { i=build(s,(s+t)/2,num*2); j=build((s+t)/2+1,t,num*2+1); } else { tree[num].sum=a[s]; return(a[s]); } tree[num].sum=i+j; return(tree[num].sum); } void insert(int s,int t,int add,int num){ if(s<=tree[num].left&&tree[num].right<=t) { tree[num].add+=add; tree[num].sum+=add*(tree[num].right-tree[num].left+1); return; } if(tree[num].add){ // 向下传递 tree[num*2].sum+=tree[num].add*(tree[num*2].right-tree[num*2].left+1); tree[num*2+1].sum+=tree[num].add*(tree[num*2+1].right-tree[num*2+1].left+1); tree[num*2].add+=tree[num].add; tree[num*2+1].add+=tree[num].add; tree[num].add=0; } if(s<=(tree[num].left+tree[num].right)/2) insert(s,t,add,num*2); if(t>(tree[num].left+tree[num].right)/2) insert(s,t,add,num*2+1); tree[num].sum=tree[num*2].sum+tree[num*2+1].sum; } long long search(int s,int t,int num){ long long i=0,j=0; if(s<=tree[num].left&&tree[num].right<=t) { return(tree[num].sum); } if(tree[num].add){ tree[num*2].sum+=tree[num].add*(tree[num*2].right-tree[num*2].left+1); tree[num*2+1].sum+=tree[num].add*(tree[num*2+1].right-tree[num*2+1].left+1); tree[num*2].add+=tree[num].add; tree[num*2+1].add+=tree[num].add; tree[num].add=0; } if(s<=(tree[num].left+tree[num].right)/2) { i=search(s,t,num*2); } if(t>(tree[num].left+tree[num].right)/2) { j=search(s,t,num*2+1); } return(i+j); } int main(){ //ifstream cin("in.txt"); int i,j,k,n,m,p,t; char s; scanf("%d%d",&n,&m); for(i=1;i<=n;i++) scanf("%lld",&a[i]); build(1,n,1); for(i=1;i<=m;i++) { scanf("\n%c",&s); if(s=='C') { scanf("%d%d%d",&j,&k,&p); if(j>k) {t=j;j=k;k=t;} insert(j,k,p,1); } else { scanf("%d%d",&j,&k); if(j>k) {t=j;j=k;k=t;} cout<<search(j,k,1)<<endl; } } return(0); }
还有一道杭电上的题目:
一样的类型,这次是修改点:
I Hate It
Time Limit : 9000/3000ms (Java/Other) Memory Limit : 32768/32768K (Java/Other)
Total Submission(s) : 11 Accepted Submission(s) : 6
Problem Description
很多学校流行一种比较的习惯。老师们很喜欢询问,从某某到某某当中,分数最高的是多少。
这让很多学生很反感。
不管你喜不喜欢,现在需要你做的是,就是按照老师的要求,写一个程序,模拟老师的询问。当然,老师有时候需要更新某位同学的成绩。
这让很多学生很反感。
不管你喜不喜欢,现在需要你做的是,就是按照老师的要求,写一个程序,模拟老师的询问。当然,老师有时候需要更新某位同学的成绩。
Input
本题目包含多组测试,请处理到文件结束。
在每个测试的第一行,有两个正整数 N 和 M ( 0<N<=200000,0<M<5000 ),分别代表学生的数目和操作的数目。
学生ID编号分别从1编到N。
第二行包含N个整数,代表这N个学生的初始成绩,其中第i个数代表ID为i的学生的成绩。
接下来有M行。每一行有一个字符 C (只取'Q'或'U') ,和两个正整数A,B。
当C为'Q'的时候,表示这是一条询问操作,它询问ID从A到B(包括A,B)的学生当中,成绩最高的是多少。
当C为'U'的时候,表示这是一条更新操作,要求把ID为A的学生的成绩更改为B。
在每个测试的第一行,有两个正整数 N 和 M ( 0<N<=200000,0<M<5000 ),分别代表学生的数目和操作的数目。
学生ID编号分别从1编到N。
第二行包含N个整数,代表这N个学生的初始成绩,其中第i个数代表ID为i的学生的成绩。
接下来有M行。每一行有一个字符 C (只取'Q'或'U') ,和两个正整数A,B。
当C为'Q'的时候,表示这是一条询问操作,它询问ID从A到B(包括A,B)的学生当中,成绩最高的是多少。
当C为'U'的时候,表示这是一条更新操作,要求把ID为A的学生的成绩更改为B。
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
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
6
5
9
View Code
1 #include <iostream> 2 #include <stdio.h> 3 #include <string.h> 4 #define INF 0x3fffffff 5 using namespace std; 6 7 const int N=200010; 8 struct Node{ 9 int left,right; 10 int max; 11 }tree[N*4]; 12 13 int a[N]; 14 15 int max(int a,int b) 16 { 17 if(a>b) return a; 18 return b; 19 } 20 21 void build(int s,int t,int r) 22 { 23 tree[r].left=s; 24 tree[r].right=t; 25 if(s==t) 26 { 27 tree[r].max=a[s]; 28 return; 29 } 30 int mid=(s+t)/2; 31 build(s,mid,r*2); 32 build(mid+1,t,r*2+1); 33 tree[r].max=max(tree[r*2].max,tree[r*2+1].max); //递归更新父节点 34 35 } 36 37 void update(int s,int t,int a,int value,int r) // s、t、分别代表根节点为r的左右两范围 38 { 39 if(tree[r].left==tree[r].right) 40 { 41 tree[r].max=value; 42 return ; 43 } 44 if(a<=(s+t)/2) 45 { 46 update(s,(s+t)/2,a,value,r*2); 47 } 48 else update((s+t)/2+1,t,a,value,r*2+1); 49 tree[r].max=max(tree[r*2].max,tree[r*2+1].max); //递归更新父节点 50 } 51 52 int query(int s,int t, int r) 53 { 54 if(s<=tree[r].left && tree[r].right<=t) 55 return tree[r].max; 56 int m1=-INF,m2=-INF; 57 if(s<=(tree[r].left+tree[r].right)/2) 58 m1=query(s,t,r*2); 59 if(t>(tree[r].left+tree[r].right)/2) 60 m2=query(s,t,r*2+1); 61 return max(m1,m2); 62 } 63 64 65 int main() 66 { 67 int n,m,i,j,p,q,f; 68 while(scanf("%d%d",&n,&m)!=EOF) 69 { 70 for(i=1;i<=n;i++) 71 { 72 scanf("\n%d",&a[i]); 73 } 74 build(1,n,1); 75 getchar(); 76 while(m--) 77 { 78 char ch; 79 scanf("%c",&ch); 80 if(ch=='Q') 81 { 82 scanf("%d%d",&p,&q); 83 if(p>q) {f=p;p=q;q=f;} 84 cout<<query(p,q,1)<<endl; 85 } 86 if(ch=='U') 87 { 88 scanf("%d%d",&p,&q); 89 update(1,n,p,q,1); 90 } 91 getchar(); 92 } 93 } 94 return 0; 95 }