您的位置:首页 > 其它

UVA 11992 线段树

2015-11-23 20:29 141 查看
input

r c m r<=20,1<=m<=20000

m行操作

1 x1 y1 x2 y2 v add v

2 x1 y1 x2 y2 v set v

3 x1 y1 x2 y2   查询该矩阵中的sum,max,min

output

对于每个3操作输出sum,max,min

做法:每行建一颗线段树

#include <cstdio>
#include <queue>
#include <cstring>
#include <iostream>
#include <cstdlib>
#include <algorithm>
#include <vector>
#include <map>
#include <set>
#include <ctime>
#include <cmath>
#define INF 0x7fffffff
#define MAX 1000000

using namespace std;

struct node
{
int v,addv,setv,sum,min,max;
};
int r,c,m,x1,yy1,x2,yy2,v,op,suma,mina,maxa;
node a[21][MAX*3];
void pushdown(int &l,int &r,int &k,int&i)
{
if(a[i][k].setv==0&&a[i][k].addv==0) return;
int m=l+((r-l)>>1),lc=k<<1,rc=k<<1|1,allv=a[i][k].setv+a[i][k].addv;
if(a[i][k].setv)        //有set操作时优先将set操作pushdown
{
a[i][lc].addv=a[i][rc].addv=a[i][k].addv;
a[i][lc].v=a[i][rc].v=a[i][lc].setv=a[i][rc].setv=a[i][k].setv;
a[i][lc].min=a[i][rc].min=a[i][lc].max=a[i][rc].max=allv;
a[i][lc].sum=(m-l+1)*allv;
a[i][rc].sum=(r-m)*allv;
a[i][k].setv=a[i][k].addv=0;
}
else                    //无set操作时只是add操作也要pushdown
{
a[i][lc].addv+=a[i][k].addv;
a[i][rc].addv+=a[i][k].addv;
a[i][lc].min+=a[i][k].addv;
a[i][rc].min+=a[i][k].addv;
a[i][lc].max+=a[i][k].addv;
a[i][rc].max+=a[i][k].addv;
a[i][lc].sum+=(m-l+1)*a[i][k].addv;
a[i][rc].sum+=(r-m)*a[i][k].addv;
a[i][k].addv=0;
}
//    printf("l:%d r:%d setv:%d add:%d\n",l,r,a[i][k].setv,a[i][k].addv);
}
void reset(int &l,int &r,int &k,int&i)
{
int m=l+((r-l)>>1),lc=k<<1,rc=k<<1|1;
a[i][k].sum=a[i][lc].sum+a[i][rc].sum+(r-l+1)*a[i][k].addv;
a[i][k].min=min(a[i][lc].min,a[i][rc].min)+a[i][k].addv;
a[i][k].max=max(a[i][lc].max,a[i][rc].max)+a[i][k].addv;
}
void setupdate(int l,int r,int k,int &i)
{
int lc=k<<1,rc=k<<1|1;
if(yy1<=l&&yy2>=r)
{
a[i][k].min=a[i][k].max=a[i][k].setv=a[i][k].v=v;
a[i][k].addv=0;
a[i][k].sum=(r-l+1)*v;
//printf("l:%d r:%d setv:%d add:%d\n",l,r,a[i][k].setv,a[i][k].addv);
return;
}
pushdown(l,r,k,i);
int m=l+((r-l)>>1);
if(yy1<=m) setupdate(l,m,lc,i);
if(yy2>m) setupdate(m+1,r,rc,i);
reset(l,r,k,i);
}
void addupdate(int l,int r,int k,int &i)
{
int lc=k<<1,rc=k<<1|1;
if(yy1<=l&&yy2>=r)
{
a[i][k].addv+=v;
a[i][k].sum+=(r-l+1)*v;
a[i][k].min+=v;
a[i][k].max+=v;
return;
}
pushdown(l,r,k,i);
int m=l+((r-l)>>1);
if(yy1<=m) addupdate(l,m,lc,i);
if(yy2>m) addupdate(m+1,r,rc,i);
reset(l,r,k,i);
}
void query(int l,int r,int k,int& i,int add)
{
if(a[i][k].setv)
{
int allv=add+a[i][k].v+a[i][k].addv;
suma+=allv*(min(r,yy2)-max(l,yy1)+1);
mina=min(mina,allv);
maxa=max(maxa,allv);
//printf("addv:%d all:%d %d %d\n",a[i][k].addv,add,mina,maxa);
return;
}
if(yy1<=l&&yy2>=r)
{
suma+=a[i][k].sum+(r-l+1)*add;
mina=min(mina,a[i][k].min+add);
maxa=max(maxa,a[i][k].max+add);
return;
}
int m=l+((r-l)>>1);
if(yy1<=m) query(l,m,k<<1,i,add+a[i][k].addv);
if(yy2>m) query(m+1,r,k<<1|1,i,add+a[i][k].addv);
}
int main()
{
freopen("/home/user/桌面/in","r",stdin);
while(scanf("%d%d%d",&r,&c,&m)==3)
{
for(int i=1;i<=r;i++) memset(a[i],0,sizeof(a[0][0])*3*c);
//memset(a,0,sizeof(a));
while(m--)
{
scanf("%d%d%d%d%d",&op,&x1,&yy1,&x2,&yy2);
if(op==2)
{
scanf("%d",&v);
for(int i=x1;i<=x2;i++) setupdate(1,c,1,i);
//for(int i=1;i<3*c;i++) printf("%d:%d %d\n",i,a[3][i].setv,a[3][i].addv);
//puts("set");
}
else if(op==1)
{
scanf("%d",&v);
for(int i=x1;i<=x2;i++) addupdate(1,c,1,i);
//for(int i=1;i<3*c;i++) printf("%d:%d %d\n",i,a[3][i].setv,a[3][i].addv);
//puts("add");
}
else
{
suma=0;
mina=INF;
maxa=-INF-1;
//printf("row:%d-%d\ncol:%d-%d\n",x1,x2,yy1,yy2);
//for(int i=1;i<=r;i++) printf("rowsum:%d\n",a[i][1].sum);
for(int i=x1;i<=x2;i++) query(1,c,1,i,0);
printf("%d %d %d\n",suma,mina,maxa);
}
}
}
//printf("time=%.3lf",(double)clock()/CLOCKS_PER_SEC);
return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: