• Comet OJ


    有一个长度为 $m$ 的整数序列 $c$,初始值都是 0

    还有一个长度为 $n$ 的操作序列,第 $i$ 个元素用三元组 $(l_{i},r_{i},v_{i})$ 描述,代表将 $c[l_{i}] sim c[r_{i}]$ 都赋值为 $v_{i}$

    有 $q$ 个询问,第 $i$ 次询问让你求出执行第 $x_{i}$ 到 $y_{i}$ 这 $y_{i}-x_{i}+1$ 个操作后序列所有整数的和.

    题解:

    首先,我们按照询问的右端点 $r$ 排序,然后依次执行时刻小于等于当前右端点的操作.

    我们要查的显然就是序列中被覆盖的时间戳在 $[l,r]$ 之间的所有元素和.

    然后就有一个套路了:我们维护四元组 $(l,r,v,k)$ 表示在第 $k$ 时刻时将 $[l,r]$ 置为 $v$.

    如果一个位置在多个时刻都被覆盖,我们就保留修改时刻最大的那个.

    所以,我们发现所有的四元组是互不相交的.

    考虑插入一个新的操作:$(l_{i},r_{i},v_{i})$,我们先找到是否有四元组盖住 $l_{i}/r_{i}$,如果有的话就都分成两个,然后再扔回 set 中.

    然后,我们再把所有在 $[l_{i},r_{i}]$ 之间的四元组全删掉,然后插入新的四元组.

    这个做法看起来十分暴力,但是我们分析一下复杂度:

    每次插入最多会新生成 3 个四元组,而一个四元组被删除后就再也不会回来.

    所以总插入数量和总删除数量不超过 $6n$,是线性的. 

    #include <cstdio> 
    #include <set> 
    #include <map> 
    #include <vector>
    #include <algorithm>
    #include <cstring>
    #include <string>
    #define N 500009 
    #define ll long long 
    #define setIO(s) freopen(s".in","r",stdin) 
    using namespace std;           
    namespace BIT 
    {
        ll c[N]; 
        int lowbit(int t) { return t&(-t); }   
        ll query(int x) 
        { 
            ll re=0;   
            for(;x>0;x-=lowbit(x)) re+=c[x];   
            return re;  
        }     
        void update(int x,ll v) { for(;x<N;x+=lowbit(x)) c[x]+=v; }      
    };        
    int n,m,Q; 
    ll answer[N];  
    struct node 
    {
        int l,r,v,d;  
        node(int l=0,int r=0,int v=0,int d=0):l(l),r(r),v(v),d(d){}  
        bool operator<(node b) const { return l<b.l; }   
    }a[N],cn[N];          
    set<node>se;          
    set<node>::iterator t;         
    struct ask{ int l,r,id;  }as[N];    
    bool cmp(ask a,ask b) { return a.r<b.r; }        
    void split(node a,int pos) 
    {    
        if(a.l==a.r||pos<=a.l||pos>a.r) return;    
        node p=a;      
        se.erase(a);  
        p.l=pos,a.r=pos-1;          
        se.insert(a); 
        se.insert(p);                       
    }
    void Insert(node a) 
    {     
        int l=a.l,r=a.r,v=a.v,d=a.d,tot=0;          
        set<node>::iterator itl,itr,it; 
        itl=se.lower_bound(node(l+1,0,0,0));                 
        if(itl!=se.begin()) --itl,split(*itl,l);                               
        itr=se.lower_bound(node(r+1,0,0,0));       
        if(itr!=se.begin()) --itr,split(*itr,r+1);    
        itl=se.lower_bound(node(l,0,0,0));  
        itr=se.lower_bound(node(r+1,0,0,0));       
        for(it=itl;it!=itr;it++)  
        {
            BIT::update((*it).d,-(ll)((*it).r-(*it).l+1)*(*it).v);            
            cn[++tot]=*it;  
        }   
        for(int i=1;i<=tot;++i) se.erase(cn[i]); 
        BIT::update(a.d,(ll)(a.r-a.l+1)*a.v);                                          
        se.insert(a);        
    }              
    int main() 
    { 
        // setIO("input");      
        int i,j; 
        scanf("%d%d%d",&n,&m,&Q);  
        for(i=1;i<=n;++i) scanf("%d%d%d",&a[i].l,&a[i].r,&a[i].v),a[i].d=i;       
        for(i=1;i<=Q;++i) scanf("%d%d",&as[i].l,&as[i].r),as[i].id=i;   
        sort(as+1,as+1+Q,cmp);     
        for(j=i=1;i<=Q;++i) 
        {    
            for(;j<=n&&a[j].d<=as[i].r;++j) Insert(a[j]);  
    
            answer[as[i].id]=BIT::query(as[i].r)-BIT::query(as[i].l-1);        
        }         
        for(i=1;i<=Q;++i) printf("%lld
    ",answer[i]);   
        return 0; 
    }
    

      

     

  • 相关阅读:
    阿里笔试题—战报交流
    2 基于梯度的攻击——PGD
    1 基于梯度的攻击——FGSM
    0 对抗样本
    自然语言处理 复习笔记 3
    自然语言处理 复习笔记 2
    自然语言处理 复习笔记 1
    GRU
    1*1卷积核的作用
    BP原理
  • 原文地址:https://www.cnblogs.com/guangheli/p/12163125.html
Copyright © 2020-2023  润新知