您的位置:首页 > 其它

uva11992区间修改线段树

2015-08-22 03:55 369 查看
数据范围很大,但是可以每行建一个线段树,化为线性的

set的优先级高于add

pushdown的时候相当于在add和sett中对一个整个的区间进行“赋值”一样,所以还要加上改sum,min1,max1的部分

三个询问可以一起做。。。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
using namespace std;

#define MAXN 4000000
//#define INF 1000000000
//每一行建一颗线段树,只要开总元素个数的数组即可,下标可以算出
int ll,rr,r,c,m,ans1,ans2,ans3,op,x1,y1,x2,y2,v;
struct point{
    int l,r,sum,max1,min1;
}tree[MAXN];
int addv[MAXN],setv[MAXN];//lazy_tag

void build(int p,int l,int r)
{
    tree[p].l=l;
    tree[p].r=r;
    tree[p].sum=0;
    tree[p].min1=0;
    tree[p].max1=0;
    if (l==r)
        return ;
    int mid=(l+r) >> 1;
    build(p<<1,l,mid);
    build(p<<1^1,mid+1,r);
    return ;
}
//优先级 set>add(当set>=0 add>0时)
void pushdown(int p)
{
    if (setv[p]>=0)
    {
        setv[p<<1]=setv[p<<1^1]=setv[p];
        addv[p<<1]=addv[p<<1^1]=0;
        tree[p<<1].sum=(tree[p<<1].r-tree[p<<1].l+1)*setv[p];
        tree[p<<1^1].sum=(tree[p<<1^1].r-tree[p<<1^1].l+1)*setv[p];
        tree[p<<1].min1=tree[p<<1^1].min1=setv[p];
        tree[p<<1].max1=tree[p<<1^1].max1=setv[p];
        setv[p]=-1;//放最后!!
    }
    if (addv[p]>0)
    {
        addv[p<<1]+=addv[p];
        addv[p<<1^1]+=addv[p];
        tree[p<<1].sum+=(tree[p<<1].r-tree[p<<1].l+1)*addv[p];
        tree[p<<1^1].sum+=(tree[p<<1^1].r-tree[p<<1^1].l+1)*addv[p];
        tree[p<<1].min1+=addv[p];
        tree[p<<1].max1+=addv[p];
        tree[p<<1^1].min1+=addv[p];
        tree[p<<1^1].max1+=addv[p];
        addv[p]=0;
    }
}
void updata(int p)
{
    tree[p].min1=min(tree[p<<1].min1,tree[p<<1^1].min1);
    tree[p].max1=max(tree[p<<1].max1,tree[p<<1^1].max1);
    tree[p].sum=tree[p<<1].sum+tree[p<<1^1].sum;
}
void add(int p,int l,int r,int v)
{
    if (tree[p].l==l && tree[p].r==r)
    {
        addv[p]+=v;
        tree[p].sum+=(r-l+1)*v;//if的同时维护
        tree[p].min1+=v;
        tree[p].max1+=v;
        return ;
    }
    pushdown(p);//pushdown要在这里用,因为之前if中的已经是可以直接判断的了
    //要向下走再下传标记
    int mid=(tree[p].l+tree[p].r) >> 1;
    if (r<=mid) add(p<<1,l,r,v);
    if (l>mid) add(p<<1^1,l,r,v);
    if (l<=mid && r>mid)
    {
        add(p<<1,l,mid,v);
        add(p<<1^1,mid+1,r,v);
    }
    updata(p);
}
void sett(int p,int l,int r,int v)
{
    if (tree[p].l==l && tree[p].r==r)
    {
        setv[p]=v;
        addv[p]=0;//这个一开始也没加
        tree[p].sum=(r-l+1)*v;
        tree[p].min1=v;
        tree[p].max1=v;
        return ;
    }
    pushdown(p);
    int mid=(tree[p].l+tree[p].r) >> 1;
    if (r<=mid) sett(p<<1,l,r,v);
    if (l>mid) sett(p<<1^1,l,r,v);
    if (l<=mid && r>mid)
    {
        sett(p<<1,l,mid,v);
        sett(p<<1^1,mid+1,r,v);
    }
    updata(p);
}

void query(int p,int l,int r)
{

    if (tree[p].l==l && tree[p].r==r)
    {
        ans1+=tree[p].sum;
        ans2=min(ans2,tree[p].min1);
        ans3=max(ans3,tree[p].max1);
        return ;
    }
    pushdown(p);
    int mid=(tree[p].l+tree[p].r) >> 1;
    if (r<=mid) query(p<<1,l,r);
    if (l>mid) query(p<<1^1,l,r);
    if (l<=mid && r>mid)
    {
        query(p<<1,l,mid);
        query(p<<1^1,mid+1,r);
    }
    updata(p);
}
int main()
{
    while (cin>>r>>c>>m)
    {
        memset(addv,0,sizeof(addv));
        memset(setv,-1,sizeof(setv));//因为可能set为0
        build(1,1,r*c);
        for (int i=1;i<=m;i++)
        {
            cin>>op>>x1>>y1>>x2>>y2;
            if (op==1)
            {
                cin>>v;
                for (int j=x1;j<=x2;j++)
                {
                    add(1,(j-1)*c+y1,(j-1)*c+y2,v);
                }
            }
            if (op==2)
            {
                cin>>v;
                for (int j=x1;j<=x2;j++)
                {
                    sett(1,(j-1)*c+y1,(j-1)*c+y2,v);
                }
            }
            if (op==3)
            {
                ans2=1000000000;
                ans1=ans3=0;
                for (int j=x1;j<=x2;j++)
                {
                    ll=(j-1)*c+y1;
                    rr=(j-1)*c+y2;
                    query(1,ll,rr);
                }
                cout<<ans1<<' '<<ans2<<' '<<ans3<<endl;
            }
       }
    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: