zoukankan      html  css  js  c++  java
  • 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]);
    }
    
  • 相关阅读:
    word设置的密码忘了怎么办?
    Navicat Report Viewer 设置 HTTP 的方法
    如何处理Navicat Report Viewer 报表
    excel密码忘记了怎么办
    Beyond Compare文本比较搜索功能详解
    Popular Cows POJ
    Problem B. Harvest of Apples HDU
    网络流模型整理
    The Shortest Statement CodeForces
    Vasya and Multisets CodeForces
  • 原文地址:https://www.cnblogs.com/suika/p/9062675.html
Copyright © 2011-2022 走看看