金华邀请赛题目D
线段树
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
struct node
{ int l,r;
int mx;
int re;
};
node lt[800000];
int n,Max;
int a[200003],b[200003];
void built(int l,int r,int k)//建树
{ lt[k].l=l;
lt[k].r=r;
lt[k].re=0;
if(l==r)
{
lt[k].mx=b[l];
return ;
}
int m=(l+r)>>1;
int t=k<<1;
built(l,m,t);
built(m+1,r,t|1);
lt[k].mx=lt[t].mx>lt[t|1].mx?lt[t].mx:lt[t|1].mx;
}
void down(int k) //这个很重要,要将上层数据下压
{
if(lt[k].re==0) return ;
lt[k].mx+=lt[k].re;
if(lt[k].l!=lt[k].r)
{
lt[k<<1].re+=lt[k].re;
lt[k<<1|1].re+=lt[k].re;
}
lt[k].re=0;
}
int va;
void up(int x,int y,int k) //更新
{
down(k);
if(x==lt[k].l&&y==lt[k].r)//成段更新
{
lt[k].re+=va;
down(k);
return ;
}
int m=(lt[k].l+lt[k].r)>>1;
int t=k<<1;
if(x<=m&&y>m)
{
up(x,m,t);
up(m+1,y,t|1);
}
else if(x>m)
{ up(x,y,t|1);down(t);}
else {up(x,y,t);down(t|1);}
lt[k].mx=lt[t].mx>lt[t|1].mx?lt[t].mx:lt[t|1].mx;
}
int _max(int x,int y,int k)//求最大值
{
down(k); //下压
if(lt[k].l==x&<[k].r==y)
{
return lt[k].mx;
}
int m=(lt[k].l+lt[k].r)>>1;
if(x<=m&&y>m)
{
return max(_max(x,m,k<<1),_max(m+1,y,k<<1|1));
}
else if(x>m)
{return _max(x,y,k<<1|1);}
else {return _max(x,y,k<<1);}
}
int main()
{
freopen("in.txt","r",stdin);
freopen("out1.txt","w",stdout);
int t,m,sum;
int i,j;
int q,x,y,t_x,t_y,k;
scanf("%d",&t);
while(t--)
{ sum=0;
scanf("%d%d%d",&n,&m,&k);
for(i=1;i<=k;sum+=a[i],i++)
scanf("%d",&a[i]);
b[k]=sum;
for(j=1;i<=n;sum=sum-a[j]+a[i],b[i]=sum,j++,i++)
scanf("%d",&a[i]);
built(k,n,1);
for(i=0;i<m;i++)
{
scanf("%d%d%d",&q,&x,&y);
switch(q)
{
case 0:
va=y-a[x];a[x]=y;t_x=x;t_y=x+k-1;
if(t_x<k) t_x=k;if(t_y>n) t_y=n;
up(t_x,t_y,1);break;
case 1:
va=a[y]-a[x];t_x=x;t_y=x+k-1;
if(t_x<k) t_x=k;if(t_y>n) t_y=n;
up(t_x,t_y,1);
va=a[x]-a[y];t_x=y;t_y=y+k-1;
if(t_x<k) t_x=k; if(t_y>n) t_y=n;
up(t_x,t_y,1);swap(a[x],a[y]);
break;
case 2:printf("%d\n",_max(x+k-1,y,1));break;
}
}
}
return 0;
}