• hdu4533 线段树维护分段函数


    更新:x1,y1,x2,y2不用long long 会wa。。

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    #define maxn 200005
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define ll long long 
    ll A[maxn<<2],B[maxn<<2],C[maxn<<2];//系数a,b,c在t[l,r]区间的取值
    
    inline void pushdown(int rt){
        A[rt<<1]+=A[rt];A[rt<<1|1]+=A[rt];
        B[rt<<1]+=B[rt];B[rt<<1|1]+=B[rt];
        C[rt<<1]+=C[rt];C[rt<<1|1]+=C[rt];
        A[rt]=B[rt]=C[rt]=0;
    }
    //区间【L,R】的a,b,c更新
    void update(int L,int R,int l,int r,int rt,ll a,ll b,ll c){
        if(L<=l && R>=r){
            A[rt]+=a;
            B[rt]+=b;
            C[rt]+=c;
            return;
        }
        int m=l+r>>1;
        if(L<=m) update(L,R,lson,a,b,c);
        if(R>m) update(L,R,rson,a,b,c);
    }
    //询问t小于等于pos的一元二次式的值
    ll query(ll t,int l,int r,int rt){
        if(l==r){
            return A[rt]*t*t+B[rt]*t+C[rt];
        }
        pushdown(rt);
        int m=l+r>>1;
        if(t<=m) return query(t,lson);
        else return query(t,rson);
    }
    void solve(ll x1,ll y1,ll x2,ll y2){
        //t如果大于max(x2,y2),那么就是覆盖了整块被子,此时a,b皆为0
        update(max(x2,y2)+1,maxn,1,maxn,1,0,0,(x2-x1)*(y2-y1));
        //a为0的状态
        if(x2<y2)//t先触碰到右边,那么t在max(x2,y1)+1到y2之间一直是线性增长的
            update(max(x2,y1)+1,y2,1,maxn,1,0,x2-x1,y1*(x1-x2));
        else //t先触碰到上边,那么t在max(x1,y2)+1到x2之间一直是线性增长的
            update(max(x1,y2)+1,x2,1,maxn,1,0,-y1+y2,x1*(y1-y2));
        //最后的情况,三个系数都不是0
        if(max(x1,y1)<min(x2,y2))
            update(max(x1,y1),min(x2,y2),1,maxn,1,1,-(x1+y1),x1*y1);
    }
    int main(){
        int T,N;
        ll x,t;
        ll x1,y1,x2,y2;
        cin >> T;
        while(T--){
            memset(A,0,sizeof A);
            memset(B,0,sizeof B);
            memset(C,0,sizeof C);
            
            scanf("%d",&N);
            for(int i=1;i<=N;i++){
                scanf("%lld%lld%lld%lld",&x1,&y1,&x2,&y2);
                solve(x1,y1,x2,y2);
            }
            scanf("%lld",&x);
            while(x--){
                scanf("%lld",&t);
                printf("%lld
    ",query(t,1,maxn,1));
            }
        }
        return 0;
    }

    wa了,为什么呢

    /**
    推公式就完事了
    要推出关于t的一元二次方程的值a,b,c关于t的函数,即t的分段函数
    */
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    #define maxn 200005
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define ll long long 
    ll A[maxn<<2],B[maxn<<2],C[maxn<<2];//系数a,b,c在t[l,r]区间的取值
    
    inline void pushdown(int rt){
        A[rt<<1]+=A[rt];A[rt<<1|1]+=A[rt];
        B[rt<<1]+=B[rt];B[rt<<1|1]+=B[rt];
        C[rt<<1]+=C[rt];C[rt<<1|1]+=C[rt];
        A[rt]=B[rt]=C[rt]=0;
    }
    //区间【L,R】的a,b,c更新
    void update(int L,int R,int l,int r,int rt,ll a,ll b,ll c){
        if(L<=l && R>=r){
            A[rt]+=a;
            B[rt]+=b;
            C[rt]+=c;
            return;
        }
        int m=l+r>>1;
        if(L<=m) update(L,R,lson,a,b,c);
        if(R>m) update(L,R,rson,a,b,c);
    }
    //询问t小于等于pos的一元二次式的值
    ll query(ll t,int l,int r,int rt){
        if(l==r){
            return A[rt]*t*t+B[rt]*t+C[rt];
        }
        pushdown(rt);
        int m=l+r>>1;
        if(t<=m) return query(t,lson);
        else return query(t,rson);
    }
    void solve(int x1,int y1,int x2,int y2){
        //t如果大于max(x2,y2),那么就是覆盖了整块被子,此时a,b皆为0
        update(max(x2,y2)+1,maxn,1,maxn,1,0,0,(x2-x1)*(y2-y1));
        //a为0的状态
        if(x2<y2)//t先触碰到右边,那么t在max(x2,y1)+1到y2之间一直是线性增长的
            update(max(x2,y1)+1,y2,1,maxn,1,0,x2-x1,y1*(x1-x2));
        else //t先触碰到上边,那么t在max(x1,y2)+1到x2之间一直是线性增长的
            update(max(x1,y2)+1,x2,1,maxn,1,0,-y1+y2,x1*(y1-y2));
        //最后的情况,三个系数都不是0
        if(max(x1,y1)<min(x2,y2))
            update(max(x1,y1),min(x2,y2),1,maxn,1,1,-(x1+y1),x1*y1);
    }
    int main(){
        int T,N;
        ll x,t;
        int x1,y1,x2,y2;
        cin >> T;
        while(T--){
            memset(A,0,sizeof A);
            memset(B,0,sizeof B);
            memset(C,0,sizeof C);
            
            scanf("%d",&N);
            for(int i=1;i<=N;i++){
                scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
                solve(x1,y1,x2,y2);
            }
            scanf("%lld",&x);
            while(x--){
                scanf("%lld",&t);
                printf("%lld
    ",query(t,1,maxn,1));
            }
        }
        return 0;
    }
  • 相关阅读:
    Bate版本控制报告
    【探路者】第五周立会报告6(总第32次)
    【探路者】第五周立会报告5(总第31次)
    【探路者】第五周立会报告4(总第30次)
    【探路者】第五周立会报告3(总第29次)
    【探路者】第五周立会报告2(总第28次)
    例行报告
    【探路者】第五周立会报告1(总第27次)
    【探路者】第四周立会报告7(总第26次)
    “Hello world!”团队第三周贡献分规则
  • 原文地址:https://www.cnblogs.com/zsben991126/p/9932617.html
Copyright © 2020-2023  润新知