• BZOJ_4636_蒟蒻的数列_线段树+动态开点


    BZOJ_4636_蒟蒻的数列_线段树+动态开点

    Description

    蒟蒻DCrusher不仅喜欢玩扑克,还喜欢研究数列
    题目描述
    DCrusher有一个数列,初始值均为0,他进行N次操作,每次将数列[a,b)这个区间中所有比k小的数改为k,他想知
    道N次操作后数列中所有元素的和。他还要玩其他游戏,所以这个问题留给你解决。

    Input

    第一行一个整数N,然后有N行,每行三个正整数a、b、k。
    N<=40000 , a、b、k<=10^9

    Output

    一个数,数列中所有元素的和

    Sample Input

    4
    2 5 1
    9 10 4
    6 8 2
    4 6 3

    Sample Output

    16

    把操作离线并从小到大排序,相当于线段树维护区间赋值操作。
    本题可以离散化也可以动态开点,我这里处理不好线段树维护离散后的区间因此写了动态开点。
    注意pushdown操作时如果没有这个儿子也要开出来。
     
    代码:
    #include <stdio.h>
    #include <string.h>
    #include <algorithm>
    #include <stdlib.h>
    using namespace std;
    #define N 40050
    #define maxn 1000000000
    typedef long long ll;
    struct A {
        int l,r,k;
    }a[N];
    bool cmp(const A &x,const A &y) {return x.k<y.k;}
    int tag[N*80],cnt,n,ls[N*80],rs[N*80];
    ll t[N*80];
    /*int make(int x) {
        return lower_bound(v+1,v+cnt+1,x)-v;
    }*/
    void pushdown(int l,int r,int &p,int w) {
        if(!p) p=++cnt;
        t[p]=1ll*w*(r-l+1); tag[p]=w;
    }
    void update(int l,int r,int x,int y,int w,int &p) {
        if(p==0) p=++cnt;
        if(x<=l&&y>=r) {
            t[p]=1ll*w*(r-l+1);
            tag[p]=w;
            return ;
        }
        int mid=(l+r)>>1;
        if(tag[p]) {
            pushdown(l,mid,ls[p],tag[p]);
            pushdown(mid+1,r,rs[p],tag[p]);
            tag[p]=0;
        }
        if(x<=mid) update(l,mid,x,y,w,ls[p]);
        if(y>mid) update(mid+1,r,x,y,w,rs[p]);
        t[p]=t[ls[p]]+t[rs[p]];
    }
    int main() {
        scanf("%d",&n);
        int i;
        for(i=1;i<=n;i++) {
            scanf("%d%d%d",&a[i].l,&a[i].r,&a[i].k);
            a[i].r--;
            /*v[++cnt]=a[i].l;
            v[++cnt]=a[i].r;*/
        }
        /*sort(v+1,v+cnt+1);
        cnt=unique(v+1,v+cnt+1)-v-1;
        printf("%d
    ",cnt);
        for(i=1;i<=cnt;i++) printf("%d
    ",v[i]); */
        sort(a+1,a+n+1,cmp);
        int root=0;
        for(i=1;i<=n;i++) {
            if(a[i].k==0) continue;
            /*printf("%d %d
    ",make(a[i].l),make(a[i].r));
            update(1,cnt,make(a[i].l),make(a[i].r),a[i].k,1);
            printf("sum=%lld
    ",t[1]);*/
            update(1,maxn,a[i].l,a[i].r,a[i].k,root);
        }
        printf("%lld
    ",t[1]);
    }
    
  • 相关阅读:
    GridView跨列
    html的积累
    什么是json?
    关于string
    Effective C# Item38:定制和支持数据绑定
    Effective C# Item44:为应用程序创建特定的异常类
    Effective C# Item42:利用特性简化反射
    Effective C# Item47:选择安全代码
    Effective C# Item43 : 避免过度使用反射
    Effective C# Item39 : 使用.NET验证
  • 原文地址:https://www.cnblogs.com/suika/p/9062675.html
Copyright © 2020-2023  润新知