Processing math: 100%

Comet OJ - Contest #14 (D转转的数据结构题) set+树状数组

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

还有一个长度为 n 的操作序列,第 i 个元素用三元组 (li,ri,vi) 描述,代表将 c[li]c[ri] 都赋值为 vi

q 个询问,第 i 次询问让你求出执行第 xiyiyixi+1 个操作后序列所有整数的和.

题解:

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

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

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

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

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

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

然后,我们再把所有在 [li,ri] 之间的四元组全删掉,然后插入新的四元组.

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

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#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\n",answer[i]);  
    return 0;
}

  

 

posted @   EM-LGH  阅读(189)  评论(0编辑  收藏  举报
努力加载评论中...
点击右上角即可分享
微信分享提示