题目大意:输入n,m,k。n个数,m个区间更新标记为1~m。n次操作,每次操作有两个数x,y表示执行第x~y个区间更新。
题解:通过差分来表示某个区间更新操作执行的次数。然后用线段树来更新区间。
#include<bits/stdc++.h> using namespace std; const int N=1E5+7; typedef long long ll; ll arr[N]; ll tt[N],cnt[N]; struct stu{ ll value,add; }tree[N+N+N]; ll l1[N],r1[N],v[N]; void bt(ll root,ll start,ll end){ tree[root].add=0; if(start==end) { tree[root].value=arr[end]; return ; } ll mid=(start+end)/2; bt(root*2,start,mid); bt(root*2+1,mid+1,end); tree[root].value=tree[root*2].value+tree[root*2+1].value; } void pushdown(ll root,ll start,ll end){ ll mid=(start+end)/2; tree[root*2].value+=(mid-start+1)*tree[root].add; tree[root*2+1].value+=(end-mid)*tree[root].add; tree[root*2].add+=tree[root].add; tree[root*2+1].add+=tree[root].add; tree[root].add=0; } void update(ll root,ll start,ll end,ll l,ll r,ll k){ if(r<start||l>end) return ; if(start>=l&&end<=r){ tree[root].value+=k*(end-start+1); tree[root].add+=k; return ; } pushdown(root,start,end); ll mid=(start+end)/2; update(root*2,start,mid,l,r,k); update(root*2+1,mid+1,end,l,r,k); tree[root].value=tree[root*2].value+tree[root*2+1].value; return ; } ll query(ll root,ll start,ll end,ll i){ if(start==end) { if(end==i) return tree[root].value; } if(start>i||i>end) return 0; pushdown(root,start,end); ll mid=(start+end)/2; return query(root*2,start,mid,i)+query(root*2+1,mid+1,end,i); } int main() { ios::sync_with_stdio(0); ll n,m,q; cin>>n>>m>>q; for(ll i=1;i<=n;i++) cin>>arr[i]; for(ll i=1;i<=m;i++) cin>>l1[i]>>r1[i]>>v[i]; bt(1,1,n); // for(ll i=1;i<=3*n;i++) cout<<tree[i].value<<endl; for(ll i=1;i<=q;i++){ ll x,y; cin>>x>>y; tt[x]++; tt[y+1]--; } ll tmp=0; for(ll i=1;i<=m;i++){ tmp+=tt[i]; cnt[i]=tmp; } for(ll i=1;i<=m;i++){ update(1,1,n,l1[i],r1[i],cnt[i]*v[i]); } for(ll i=1;i<=n;i++) cout<<query(1,1,n,i)<<" "; return 0; }
原文地址:https://www.cnblogs.com/Accepting/p/12255263.html
时间: 2024-10-12 22:15:22