hdu 4578 线段树

思路:本来写了一个比较短的代码,并且各函数间的重用性比较高,就是结果悲剧的超时了...就是保证每个区间只有一种操作,那么更新时就要更新子节点的子节点,需要递归更新,结果是可想而知。其实这种做法是可以过得,只要将复杂度转移到求和上去(测试数据对求和操作应该要求不严)。但那样就不能直接保存p的三种情况值,因为这样会使得常数级非常大,超时。

所以就要找到多重操作并存的方法。对于置为c,这个容易解决。关键是加和乘。思路见代码注释

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#define lson(x) x<<1
#define rson(x) x<<1|1
#define Maxn 100010
#define mod 10007
using namespace std;
struct Tree{
    int l,r;
    __int64 s[4],c,add,mul;//add是对子节点的加量,mul是对子节点的乘量,并不是对本节点的操作,c是判断是否置为c
    int mid()
    {
        return (l+r)>>1;
    }
}tree[Maxn*4];
int ans;
void BuildTree(int l,int r,int po)
{
    tree[po].l=l,tree[po].r=r,tree[po].c=0,tree[po].s[2]=tree[po].s[3]=tree[po].s[1]=0,tree[po].c=tree[po].add=0,tree[po].mul=1;
    if(l==r)
        return ;
    int mid=tree[po].mid();
    BuildTree(l,mid,lson(po));
    BuildTree(mid+1,r,rson(po));
}
void calculate(int po,int ty,__int64 c)
{//根据平方式和三次方式算出来的相对应一次式的增量
    if(ty==1){
    tree[po].s[3]+=3*c*tree[po].s[2]+3*c*c *tree[po].s[1] +c*c*c*(tree[po].r-tree[po].l+1);
    tree[po].s[2]+=2*tree[po].s[1]*c +c*c*(tree[po].r-tree[po].l+1);
    tree[po].s[1]+=c*(tree[po].r-tree[po].l+1);
    tree[po].add+=c;
    tree[po].add%=mod;
    }
    if(ty==2){
    tree[po].s[1]*=c;
    tree[po].s[2]*=c*c;
    tree[po].s[3]*=c*c*c;
    tree[po].add=tree[po].add*c%mod;
    tree[po].mul=tree[po].mul*c%mod;
    }
    if(ty==3){
    tree[po].s[1]=c*(tree[po].r-tree[po].l+1) ;
    tree[po].s[2]=c*c*(tree[po].r-tree[po].l+1) ;
    tree[po].s[3]=c*c*c*(tree[po].r-tree[po].l+1) ;
    tree[po].add=0;
    tree[po].mul=1;
    tree[po].c=c;
    }
    tree[po].s[3]%=mod;
    tree[po].s[2]%=mod;
    tree[po].s[1]%=mod;
}
void down(int po)
{
    if(tree[po].c){//如果遇到的是值为c,那么具有优先权将其子节点全置为c.
        tree[lson(po)].add=tree[rson(po)].add=0;
        tree[lson(po)].mul=tree[rson(po)].mul=1;
        tree[lson(po)].c=tree[rson(po)].c=tree[po].c;
        tree[lson(po)].s[1]=tree[po].c*(tree[lson(po)].r-tree[lson(po)].l+1) ;
        tree[lson(po)].s[2]=tree[po].c*tree[po].c *(tree[lson(po)].r-tree[lson(po)].l+1) ;
        tree[lson(po)].s[3]=tree[po].c*tree[po].c *tree[po].c *(tree[lson(po)].r-tree[lson(po)].l+1) ;
        tree[rson(po)].s[1]=tree[po].c*(tree[rson(po)].r-tree[rson(po)].l+1) ;
        tree[rson(po)].s[2]=tree[po].c*tree[po].c *(tree[rson(po)].r-tree[rson(po)].l+1) ;
        tree[rson(po)].s[3]=tree[po].c*tree[po].c *tree[po].c *(tree[rson(po)].r-tree[rson(po)].l+1) ;
        tree[po].c=0;
        tree[lson(po)].s[1]%=mod;
        tree[lson(po)].s[2]%=mod;
        tree[lson(po)].s[3]%=mod;
        tree[rson(po)].s[1]%=mod;
        tree[rson(po)].s[2]%=mod;
        tree[rson(po)].s[3]%=mod;
    }
   if(tree[po].add != 0 || tree[po].mul != 1)
    {
        //对左儿子进行处理
        //本来的x变成了x*tree[po].mul;
        //将乘法的优先权置为比加高,那么当子节点加过一个值m,当再次对其进行乘y的时候,其实就是加了m*y,乘法同理。
        tree[lson(po)].add=(tree[po].mul*tree[lson(po)].add+tree[po].add)%mod;//修改子节点的加法增量
        tree[lson(po)].mul=tree[lson(po)].mul*tree[po].mul%mod;//修改乘法增量
        //下面的求和其实就是将ty==1和ty==2一起算了,其乘法的优先级高,故x显示被乘了tree[po].mul;
        tree[lson(po)].s[3]=tree[po].mul*tree[po].mul*tree[po].mul*tree[lson(po)].s[3];
        tree[lson(po)].s[3]=(tree[lson(po)].s[3]+3*tree[po].mul*tree[po].mul*tree[po].add*tree[lson(po)].s[2]);
        tree[lson(po)].s[3]=(tree[lson(po)].s[3]+3*tree[po].mul*tree[po].add*tree[po].add*tree[lson(po)].s[1]);
        tree[lson(po)].s[3]=(tree[lson(po)].s[3]+(tree[lson(po)].r-tree[lson(po)].l+1)*tree[po].add*tree[po].add*tree[po].add);
        tree[lson(po)].s[2]=(tree[po].mul*tree[po].mul*tree[lson(po)].s[2]+2*tree[po].add*tree[po].mul*tree[lson(po)].s[1]+(tree[lson(po)].r-tree[lson(po)].l+1)*tree[po].add*tree[po].add) ;
        tree[lson(po)].s[1]=(tree[lson(po)].s[1]*tree[po].mul+(tree[lson(po)].r-tree[lson(po)].l+1)*tree[po].add);
        tree[lson(po)].s[1]%=mod;
        tree[lson(po)].s[2]%=mod;
        tree[lson(po)].s[3]%=mod;
        //对右儿子进行处理,同左儿子
        tree[rson(po)].add=(tree[po].mul*tree[rson(po)].add+tree[po].add)%mod;
        tree[rson(po)].mul=tree[rson(po)].mul*tree[po].mul%mod;
        tree[rson(po)].s[3]=tree[po].mul*tree[po].mul*tree[po].mul*tree[rson(po)].s[3];
        tree[rson(po)].s[3]=(tree[rson(po)].s[3]+3*tree[po].mul*tree[po].mul*tree[po].add*tree[rson(po)].s[2]);
        tree[rson(po)].s[3]=(tree[rson(po)].s[3]+3*tree[po].mul*tree[po].add*tree[po].add*tree[rson(po)].s[1]);
        tree[rson(po)].s[3]=(tree[rson(po)].s[3]+(tree[rson(po)].r-tree[rson(po)].l+1)*tree[po].add*tree[po].add*tree[po].add);
        tree[rson(po)].s[2]=(tree[po].mul*tree[po].mul*tree[rson(po)].s[2]+2*tree[po].add*tree[po].mul*tree[rson(po)].s[1]+(tree[rson(po)].r-tree[rson(po)].l+1)*tree[po].add*tree[po].add) ;
        tree[rson(po)].s[1]=(tree[rson(po)].s[1]*tree[po].mul+(tree[rson(po)].r-tree[rson(po)].l+1)*tree[po].add);
        tree[rson(po)].s[1]%=mod;
        tree[rson(po)].s[2]%=mod;
        tree[rson(po)].s[3]%=mod;
        tree[po].add = 0;
        tree[po].mul = 1;
    }
}
void update(int l,int r,int ty,int c,int po)
{
    if(l<=tree[po].l&&r>=tree[po].r)
    {
        calculate(po,ty,(__int64)c);//计算本节点
        return ;
    }
    down(po);
    int mid=tree[po].mid();
    if(r<=mid)
    update(l,r,ty,c,lson(po));
    else
        if(l>=mid+1)
        update(l,r,ty,c,rson(po));
    else{
        update(l,mid,ty,c,lson(po));
        update(mid+1,r,ty,c,rson(po));
    }
    tree[po].s[1]=(tree[lson(po)].s[1]+tree[rson(po)].s[1])%mod;
    tree[po].s[2]=(tree[lson(po)].s[2]+tree[rson(po)].s[2])%mod;
    tree[po].s[3]=(tree[lson(po)].s[3]+tree[rson(po)].s[3])%mod;
}
void get_Sum(int l,int r,int p,int po)
{
    if(l<=tree[po].l&&r>=tree[po].r)
    {
        ans+=tree[po].s[p];
        ans%=mod;
        return ;
    }
    down(po);
    int mid=tree[po].mid();
    if(r<=mid)
    get_Sum(l,r,p,lson(po));
    else
        if(l>=mid+1)
        get_Sum(l,r,p,rson(po));
    else{
        get_Sum(l,mid,p,lson(po));
        get_Sum(mid+1,r,p,rson(po));
    }
    tree[po].s[1]=(tree[lson(po)].s[1]+tree[rson(po)].s[1])%mod;
    tree[po].s[2]=(tree[lson(po)].s[2]+tree[rson(po)].s[2])%mod;
    tree[po].s[3]=(tree[lson(po)].s[3]+tree[rson(po)].s[3])%mod;
}
int main()
{
    int n,i,j,l,r,c,p,m,x;
    while(scanf("%d%d",&n,&m)!=EOF,n&&m)
    {
        BuildTree(1,n,1);
        for(i=1;i<=m;i++)
        {
            scanf("%d%d%d%d",&x,&l,&r,&c);
            if(x==1){
                update(l,r,1,c,1);
            }
            if(x==2){
                update(l,r,2,c,1);
            }
            if(x==3){
                update(l,r,3,c,1);
            }
            if(x==4){
                ans=0;
                get_Sum(l,r,c,1);
                printf("%d\n",ans);
            }
        }
    }
    return 0;
}

 

posted @ 2013-08-11 12:51  fangguo  阅读(300)  评论(0编辑  收藏  举报