zoukankan      html  css  js  c++  java
  • [APIO2019]路灯

    XXXIII.[APIO2019]路灯

    实际上本来是在刷CDQ分治的题来着的,但是CDQ分治是众所周知地抽象,所以在碰到三维数点问题时,除非卡空间,否则一律请选择树套树……

    我们可以用 set 来维护连通性。显然,若 \([l,r]\) 这一段的路灯全亮,则所有 \(a,b\in[l,r+1]\) 都是合法的。

    考虑差分。当一段 \([l,r]\) 初次联通,就矩形加 \(T-t\),其中 \(T\) 是总时间,\(t\) 是当前时间;当其初次不连通,就矩形减 \(T-t\)

    维护联通与否可以使用珂朵莉树,或者说,setpair

    明显,这是带时间轴矩形加问题,是三维数点问题,鉴于CDQ太难写,我选择BIT套权值线段树。

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    int n,m,rt[300100],cnt;
    #define mid ((l+r)>>1)
    struct node{int lson,rson,tag;}seg[20010000];
    void modify(int &x,int l,int r,int L,int R,int val){
    	if(l>R||r<L)return;
    	if(!x)x=++cnt;
    	if(L<=l&&r<=R)seg[x].tag+=val;
    	else modify(seg[x].lson,l,mid,L,R,val),modify(seg[x].rson,mid+1,r,L,R,val);
    }
    int query(int x,int l,int r,int P){
    	if(l>P||r<P||!x)return 0;
    	return seg[x].tag+query(seg[x].lson,l,mid,P)+query(seg[x].rson,mid+1,r,P);
    }
    void ADD(int x,int L,int R,int val){while(x<=n)modify(rt[x],1,n,L,R,val),x+=x&-x;}
    int SUM(int x,int P){int ret=0;while(x)ret+=query(rt[x],1,n,P),x-=x&-x;return ret;}
    void ADD(int l,int r,int val){ADD(l,l,r,val),ADD(r+1,l,r,-val);}
    set<pair<int,int> >s;
    char str[300100],rts[10];
    int main(){
    	scanf("%d%d",&n,&m),scanf("%s",str+1);
    	for(int i=1,j=1;i<=n;i=j){
    		while(j<=n&&str[i]==str[j])j++;
    		if(str[i]=='1')s.insert(make_pair(i,j-1)),ADD(i,j-1,m);
    	}
    	for(int i=1,a,b;i<=m;i++){
    		scanf("%s%d",rts,&a);
    		if(rts[0]=='t'){
    			if(str[a]=='1'){
    				auto it=--s.upper_bound(make_pair(a,0x3f3f3f3f));
    				int L=it->first,R=it->second;s.erase(it);
    				ADD(L,R,i-m);
    				if(L!=a)ADD(L,a-1,m-i),s.insert(make_pair(L,a-1));
    				if(R!=a)ADD(a+1,R,m-i),s.insert(make_pair(a+1,R));
    			}else{
    				auto it=s.lower_bound(make_pair(a,0x3f3f3f3f));
    				int L=a,R=a;
    				if(it!=s.end()&&it->first==a+1)ADD(it->first,it->second,i-m),R=it->second,it=s.erase(it);
    				if(it!=s.begin()&&(--it)->second==a-1)ADD(it->first,it->second,i-m),L=it->first,s.erase(it);
    				ADD(L,R,m-i),s.insert(make_pair(L,R)); 
    			}
    //			for(auto i:s)printf("(%d %d)",i.first,i.second);puts("");
    			str[a]^=1;
    //			printf("%s\n",str+1);
    		}else{
    			scanf("%d",&b),b--;
    			int ret=SUM(a,b);
    			auto it=s.upper_bound(make_pair(a,0x3f3f3f3f));
    			if(it!=s.begin()){
    				--it;
    				if(it->first<=a&&it->second>=b)ret+=i-m;
    			}
    			printf("%d\n",ret);
    		}
    	}
    	return 0;
    }
    

  • 相关阅读:
    ABP框架使用(版本3.3.1)
    [转载] 基于.NetCore和ABP框架如何让Windows服务执行Quartz定时作业
    ABP框架使用(版本3.3.1)
    【转载】abp 调试
    如何利用Azure DevOps快速实现自动化构建、测试、打包及部署
    MongoDB语法
    python 笔记第一课
    8.4 圆柱类设计-类组合
    8.3 人事管理类的设计与实现-类组合
    8.2 方孔钱币类设计-类组合
  • 原文地址:https://www.cnblogs.com/Troverld/p/14611613.html
Copyright © 2011-2022 走看看