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 #include2 #include 3 #include 4 #include 5 #include 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 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