Codeforces Round #179 (Div. 2) C:http://codeforces.com/problemset/problem/296/C
题意:给你一个序列,然后有两种操作,第一种操作是区间加上一个数,第二种操作也是区间操作 1 3 但是这里的区间不是对原序列,而是指第一种操作,1 3,表示把1,2,3三种操作都执行一遍。求所有的操作结束之后原来数组的数。
题解:先考虑一个简单的问题,就是只有第一种操作,就是区间加上一个数。这里没有查询,所以,先加和后加没有区别。所以或一个图就可以知道。我们可以这么搞,用一个vector<int>ll[n],rr[N],ll[i]记录以i为左端更新的那种操作,rr[i]表示以i为右端点的那些更新,as 表示当前数最终应该加的值,当遇到以i开始的时候,as+=这个更新的值,遇到i结尾的时候,as-=这个更新值,这样就可以for一遍就可以了。这样就解决的这个简单的问题,现在来考虑这个题目,也就是二级操作,同理,二级操作也可以了采用这种方式,来统计数操作执行的次数,然后就转化成一级问题,不过此时一级操作的更新值变为原来的值*执行的次数。

1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 #include<vector> 6 using namespace std; 7 const int N=1e5+100; 8 long long a[N],b[N],c[N]; 9 int n,m,k; 10 vector<int>ll[N],rr[N],l[N],r[N]; 11 struct Node{ 12 int l,r; 13 long long val; 14 }num[N],temp[N]; 15 int t1,t2; 16 int main(){ 17 while(~scanf("%d%d%d",&n,&m,&k)){ 18 memset(a,0,sizeof(a)); 19 for(int i=1;i<=n;i++){ 20 scanf("%I64d",&a[i]); 21 } 22 for(int i=1;i<=m;i++){ 23 scanf("%d%d%I64d",&num[i].l,&num[i].r,&b[i]); 24 ll[num[i].l].push_back(i); 25 rr[num[i].r].push_back(i); 26 num[i].val=0; 27 } 28 for(int i=1;i<=k;i++){ 29 scanf("%d%d",&temp[i].l,&temp[i].r); 30 l[temp[i].l].push_back(i); 31 r[temp[i].r].push_back(i); 32 } 33 long long as=0; 34 memset(c,0,sizeof(c)); 35 for(int i=1;i<=m;i++){ 36 as+=l[i].size(); 37 c[i]+=as; 38 as-=r[i].size(); 39 } 40 for(int i=1;i<=m;i++){ 41 num[i].val=c[i]*b[i]; 42 } 43 as=0; 44 for(int i=1;i<=n;i++){ 45 for(int j=0;j<ll[i].size();j++) 46 as+=num[ll[i][j]].val; 47 a[i]+=as; 48 for(int j=0;j<rr[i].size();j++) 49 as-=num[rr[i][j]].val; 50 if(i!=n) 51 printf("%I64d ",a[i]); 52 } 53 printf("%I64d ",a[n]); 54 } 55 }