• 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
    ",ans);
                }
            }
        }
        return 0;
    }
  • 相关阅读:
    软件实施工程师是一个什么样的工作?他的具体工作内容是什么?发展前景怎样?
    做金融(基金、证券)方面的软件实施工程师有没有发展前途?职业发展空间如何。
    做软件实施工程师的一点建议
    系统实施工程师主要工作职则
    软件实施工程师
    UE编辑器编译和运行java设置
    猜数字
    猜数字
    Problem G
    Problem G
  • 原文地址:https://www.cnblogs.com/wangfang20/p/3251211.html
Copyright © 2020-2023  润新知