zoukankan      html  css  js  c++  java
  • BZOJ4631 踩气球

    题解

    考虑每一次踩气球对答案有贡献,当且仅当踩爆的是盒子中最后一个气球,这时设当这个气球所在的盒子是$x$,多出来的区间就是,左端点在与$x$左侧相邻的一段空盒子中,且右端点在右侧相邻的一段空盒子中的这样的区间。

    由于本题强制在线,我们考虑用并查集$+$线段树$+$启发式合并维护,把一段连续的空盒子看作一个连通块,用并查集维护,并查集上的祖先是连通块的右端点同时记录左端点。初始时若有熊孩子的区间是$[L,R]$,则类似主席树在以$R$为根的线段树中插入一个$L$,统计一个段连续空盒子$[u,v]$的答案只需统计这个连通块所对应的线段树中大于等于$L$的数的数量即可。由于每一次修改最多改变三个连通块的信息,因此我们直接统计每一次操作对答案的贡献即可。

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    #define LL long long
    #define M 400020
    #define mid ((l+r)>>1)
    using namespace std;
    int read(){
    	int nm=0,fh=1; char cw=getchar();
    	for(;!isdigit(cw);cw=getchar()) if(cw=='-') fh=-fh;
    	for(;isdigit(cw);cw=getchar()) nm=nm*10+(cw-'0');
    	return nm*fh;
    }
    int n,m,T,f[M],minn[M],sum[M*15],L[M*15],R[M*15];
    int u,v,rem[M],cnt,rt[M],ans;
    int fd(int x){return f[x]==x?x:(f[x]=fd(f[x]));}
    void ins(int &x,int pre,int l,int r,int pos){
    	x=++cnt,sum[x]=sum[pre]+1,L[x]=L[pre],R[x]=R[pre];
    	if(l==r) return;
    	if(pos<=mid) ins(L[x],L[pre],l,mid,pos);
    	else ins(R[x],R[pre],mid+1,r,pos);
    }
    int merge(int x,int y){
    	if(!x||!y) return x+y; sum[x]=sum[x]+sum[y];
    	L[x]=merge(L[x],L[y]),R[x]=merge(R[x],R[y]);
    	return x;
    }
    int query(int x,int l,int r,int pos){
    	if(l>=pos) return sum[x];
    	if(r<pos||!sum[x]) return 0;
    	return query(L[x],l,mid,pos)+query(R[x],mid+1,r,pos);
    }
    int getans(int x){
    	if(rem[x=fd(x)]) return 0;
    	return query(rt[x],1,n,minn[x]);
    }
    int main(){
    	n=read(),T=read(),ans=0;
    	for(int i=1;i<=n;i++) rem[i]=read(),f[i]=minn[i]=i;
    	while(T--) u=read(),v=read(),ins(rt[v],rt[v],1,n,u);
    	for(T=read();T;T--,printf("%d
    ",ans)){
    		u=read(),u=(u+ans-1)%n+1,rem[u]--;
    		if(!rem[u]){
    			if(rem[u-1]==0&&u>1) minn[u]=minn[u-1],ans-=getans(u-1),f[u-1]=u,rt[u]=merge(rt[u],rt[u-1]);
    			if(rem[u+1]==0&&u<n) ans-=getans(fd(u+1)),minn[f[u]=fd(u+1)]=minn[u],rt[fd(u)]=merge(rt[fd(u+1)],rt[u]);
    			ans+=getans(fd(u));
    		}
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    Public Sale(巴什博弈)
    Harmonic Value Description (思维+找规律)
    放苹果+N的划分(青理工校赛J题) (动归)
    线段树求逆序数+北化校赛D题
    写给自己
    Euclid's Game (博弈论)
    Bear and Blocks (dp+思维)
    Maximum splitting(找规律+思维)
    Bone Collector II(DP+第K优解)
    Codeforces 950E Data Center Maintenance ( 思维 && 强连通分量缩点 )
  • 原文地址:https://www.cnblogs.com/OYJason/p/9620891.html
Copyright © 2011-2022 走看看