题目链接:http://acm.nefu.edu.cn/JudgeOnline/problemShow.php?problem_id=1247
解:
线段树的懒惰标记的运用。需要注意的点就是添加超过n时的区间更新。
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <cstdlib>
using namespace std;
const int maxn = 1e5+50;
int a[maxn];
struct tree{
int l,r,node;
int val,id,lazy;
}seg[maxn<<2];
void pushup(int node)
{
if(seg[node<<1].val>seg[node<<1|1].val)
{
seg[node].val=seg[node<<1].val;
seg[node].id=seg[node<<1].id;
}
else
{
seg[node].val=seg[node<<1|1].val;
seg[node].id=seg[node<<1|1].id;
}
}
void pushdown(int node){
if(seg[node].lazy)
{
seg[node<<1].lazy+=seg[node].lazy;
seg[node<<1|1].lazy+=seg[node].lazy;
seg[node<<1].val+=seg[node].lazy;
seg[node<<1|1].val+=seg[node].lazy;
seg[node].lazy=0;
}
}
void build(int l,int r,int node)
{
seg[node].l=l;seg[node].r=r;seg[node].lazy=0;
if(l==r){seg[node].val=a[l];seg[node].id=l;return ;}
int mid=(l+r)/2;
build(l,mid,node<<1);
build(mid+1,r,node<<1|1);
pushup(node);
}
void update(int l,int r,int node,int k){
if(l<=seg[node].l&&seg[node].r<=r)
{
seg[node].val+=k;
seg[node].lazy+=k;
return ;
}
pushdown(node);
int mid=(seg[node].l+seg[node].r)/2;
if(mid>=l)
update(l,r,node<<1,k);
if(r>mid)
update(l,r,node<<1|1,k);
pushup(node);
}
void show(int node){
cout<<"Node:"<<node<<endl;
cout<<"L:"<<seg[node].l<<" R:"<<seg[node].r<<endl;
cout<<"Value:"<<seg[node].val<<endl;
cout<<"Lazy:"<<seg[node].lazy<<endl;
cout<<endl;
if(seg[node].l==seg[node].r)return ;
show(node<<1);
show(node<<1|1);
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
build(1,n,1);
while(m--)
{
int c1,c2;
scanf("%d%d",&c1,&c2);
if(seg[1].id+c1<=n)
update(seg[1].id+1,seg[1].id+c1,1,c2);
else
{
if(seg[1].id+1<=n)
{
int tmp=seg[1].id;
update(tmp+1,n,1,c2);
update(1,tmp+c1-n,1,c2);
}
else
update(1,c1,1,c2);
}
printf("%d %d\n",seg[1].id,seg[1].val);
//show(1);
}
}
return 0;
}