luoguP5445 [APIO2019]路灯 树套树+set

code: 

#include <vector> 
#include <cstdio>  
#include <cstring>
#include <map> 
#include <set>
#include <algorithm>  
#define N 300005 
#define MAX 320005  
#define setIO(s) freopen(s".in","r",stdin) ,freopen(s".out","w",stdout)     
using namespace std;    
int n;          
int rt[MAX];            
namespace tr { 
    #define lson s[x].ls 
    #define rson s[x].rs        
    int tot;  
    int newnode() { return ++tot; }    
    int lowbit(int x) { return x&(-x); }   
    struct node {
        int ls,rs,sum;    
    }s[MAX*100];      
    void update(int &x,int l,int r,int p,int v) 
    {   
        if(!x) x=newnode();   
        s[x].sum+=v;    
        if(l==r) return; 
        int mid=(l+r)>>1; 
        if(p<=mid) update(lson,l,mid,p,v); 
        else update(rson,mid+1,r,p,v);   
    }
    int query(int x,int l,int r,int L,int R) 
    {
        if(!x) return 0; 
        if(l>=L&&r<=R) return s[x].sum;   
        int mid=(l+r)>>1,re=0;    
        if(L<=mid) re+=query(lson,l,mid,L,R); 
        if(R>mid)  re+=query(rson,mid+1,r,L,R);      
        return re;   
    }    
    void upd(int x,int y,int v) 
    {
        for(int i=x;i<=N;i+=lowbit(i)) 
            update(rt[i],1,N,y,v);     
    }
    int que(int x,int y) 
    {
        int re=0; 
        for(int i=x;i;i-=lowbit(i)) 
            re+=query(rt[i],1,N,1,y);    
        return re;   
    }
    #undef lson 
    #undef rson 
};  
char str[MAX];  
// 断点在 i->i+1   
set<int>S;   
set<int>::iterator it;   
int Q,T,swi[N];     
void con(int x,int y) 
{        
    it=S.lower_bound(x);     
    int l,r,L,R;  
    if(it==S.begin()) l=1,r=x;     
    else --it,l=(*it)+1,r=x;        
    it=S.lower_bound(x);    
    it++;  
    if(it==S.end()) L=x+1,R=n+1;    
    else L=x+1,R=(*it);        
    S.erase(x);               
    tr::upd(l,L,Q-T);         
    tr::upd(l,R+1,T-Q);   
    tr::upd(r+1,L,T-Q);     
    tr::upd(r+1,R+1,Q-T);    
}  
void clo(int x,int y) 
{      
    // printf("%d %d\n",x,y);  
    S.insert(x);   
    it=S.lower_bound(x);   
    int l,r,L,R;                 
    if(it==S.begin()) l=1,r=x;   
    else --it,l=(*it)+1,r=x;   
    it=S.lower_bound(x);     
    it++;   
    if(it==S.end()) L=x+1,R=n+1;   
    else L=x+1,R=(*it);          
    tr::upd(l,L,T-Q);    
    tr::upd(l,R+1,Q-T);   
    tr::upd(r+1,L,Q-T);           
    tr::upd(r+1,R+1,T-Q);     
}
int ask(int x,int y) 
{           
    int re=tr::que(x,y);    
    set<int>::iterator X,Y;        
    X=S.lower_bound(x); 
    Y=S.lower_bound(y);    
    if(X==Y) re-=Q-T;
    return re;    
}   
int main() {
    // setIO("input");    
    int i,j;         
    scanf("%d%d%s",&n,&Q,str+1);              
    // t=0   
    for(i=1;i<=n;++i) S.insert(i);                 
    for(i=1;i<=n;++i) if(str[i]=='1') con(i,i+1),swi[i]=1;    
    for(T=1;T<=Q;++T) 
    { 
        scanf("%s",str); 
        if(str[0]=='t') 
        { 
            int x; 
            scanf("%d",&x);  
            if(swi[x]) clo(x,x+1); 
            else con(x,x+1);  
            swi[x]^=1; 
        } 
        else 
        { 
            int x,y; 
            scanf("%d%d",&x,&y);   
            printf("%d\n",ask(x,y)); 
        }
    }     
    return 0;
}

  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值