zoukankan      html  css  js  c++  java
  • bzoj5017[Snoi2017]炸弹

    bzoj5017[Snoi2017]炸弹

    luoguP5025

    给定n个炸弹和它们的爆炸半径,在爆炸半径中的其它炸弹会被引爆,求每个炸弹爆炸后一共能引爆几个炸弹
     
    从每个炸弹向它能引爆的炸弹连边
    因为它能引爆的炸弹是一个区间,所以可以用线段树优化一下
    然后缩点,同时记录每个强连通分量中,最小和最大点的编号
    最后dfs一遍用每条边的终点答案更新起点答案,也就是每个炸弹能炸掉的最左/右边的炸弹的编号,输出的时候用r[scc[i]]-l[scc[i]]+1就行了
    最后输出的时候要开long long,不然就乘爆了
    因为这个调了很久, 最后还是@北辰yama大佬帮我指出了错误,感谢%%%

    #include<cstdio>
    #include<algorithm>
    #include<iostream>
    #include<cmath>
    #include<iomanip>
    #include<queue>
    #include<cstring>
    #define R register
    #define EN std::puts("")
    #define LL long long
    inline LL read(){
    	LL x=0,y=1;
    	char c=std::getchar();
    	while(c<'0'||c>'9'){if(c=='-') y=0;c=std::getchar();}
    	while(c>='0'&&c<='9'){x=x*10+(c^48);c=std::getchar();}
    	return y?x:-x;
    }
    struct datae{
    	int from,to;
    }e[10000006];
    int n,nn;
    LL x[500006],banjing[500006];
    int in[2000006];
    int fir[2000006],nex[20000006],to[20000006],etot;
    struct tr{
    	tr *ls,*rs;
    	int id;
    }dizhi[1000006],*root=&dizhi[0];
    int tot;
    int idtol[20000006],idtor[20000006];
    int low[2000006],dfn[2000006],dfscnt;
    int scc[2000006],sccminid[2000006],sccmaxid[2000006],scccnt;
    int vis[2000006];
    int stack[2000006],top;
    inline void updatamin(int &xx,int xxx){(xx>xxx)&&(xx=xxx);}
    inline void updatamax(int &xx,int xxx){(xx<xxx)&&(xx=xxx);}
    inline void add(int u,int v,int tmp){
    	to[++etot]=v;
    	if(tmp) e[etot].from=u,e[etot].to=v;
    	nex[etot]=fir[u];fir[u]=etot;
    }
    void build(tr *tree,int l,int r){
    	if(l==r) return tree->id=idtol[l]=idtor[l]=l,void();
    	int mid=(l+r)>>1;
    	tree->ls=&dizhi[++tot];tree->rs=&dizhi[++tot];
    	build(tree->ls,l,mid);build(tree->rs,mid+1,r);
    	tree->id=++nn;
    	idtol[nn]=l;idtor[nn]=r;
    	add(tree->id,tree->ls->id,1);add(tree->id,tree->rs->id,1);
    }
    void addtree(tr *tree,int l,int r,int ql,int qr,int u){
    	if(ql<=l&&r<=qr){
    		if(tree->id!=u) add(u,tree->id,1);
    		return;
    	}
    	int mid=(l+r)>>1;
    	if(ql<=mid) addtree(tree->ls,l,mid,ql,qr,u);
    	if(qr>mid) addtree(tree->rs,mid+1,r,ql,qr,u);
    }
    inline int dayu(LL xx){
    	R int l=1,r=n,mid,ret;
    	while(l<=r){
    		mid=(l+r)>>1;
    		if(x[mid]>=xx) ret=mid,r=mid-1;
    		else l=mid+1;
    	}
    	return ret;
    }
    inline int xiaoyu(LL xx){
    	R int l=1,r=n,mid,ret;
    	while(l<=r){
    		mid=(l+r)>>1;
    		if(x[mid]<=xx) ret=mid,l=mid+1;
    		else r=mid-1;
    	}
    	return ret;
    }
    void tarjan(R int u){
    	dfn[u]=low[u]=++dfscnt;
    	stack[top++]=u;
    	for(R int i=fir[u];i;i=nex[i]){
    		R int v=to[i];
    		if(!dfn[v]){
    			tarjan(v);
    			updatamin(low[u],low[v]);
    		}
    		else if(!scc[v]) updatamin(low[u],low[v]);
    	}
    	if(dfn[u]==low[u]){
    		scccnt++;
    		sccminid[scccnt]=1e9;
    		do{
    			top--;
    			updatamin(sccminid[scccnt],idtol[stack[top]]);
    			updatamax(sccmaxid[scccnt],idtor[stack[top]]);
    			scc[stack[top]]=scccnt;
    		}while(stack[top]!=u);
    	}
    }
    void dfs(R int u){
    	vis[u]=1;
    	for(R int i=fir[u];i;i=nex[i]){
    		R int v=to[i];
    		if(vis[v]){
    			updatamin(sccminid[u],sccminid[v]);
    			updatamax(sccmaxid[u],sccmaxid[v]);
    		}
    		else{
    			dfs(v);
    			updatamin(sccminid[u],sccminid[v]);
    			updatamax(sccmaxid[u],sccmaxid[v]);
    		}
    	}
    }
    int main(){
    	nn=n=read();
    	LL minx=2e18,maxx=-2e18;
    	for(R int i=1;i<=n;i++){
    		x[i]=read();banjing[i]=read();
    		minx=std::min(minx,x[i]);maxx=std::max(maxx,x[i]);
    	}
    	build(root,1,n);
    	for(R int i=1;i<=n;i++){
    		if(!banjing[i]) continue;
    		int lll=dayu(std::max(x[i]-banjing[i],minx)),rrr=xiaoyu(std::min(maxx,x[i]+banjing[i]));
    		addtree(root,1,n,lll,rrr,i);
    	}
    	for(R int i=1;i<=nn;i++)
    		if(!dfn[i]) tarjan(i);
    	std::memset(fir,0,sizeof fir);std::memset(nex,0,sizeof nex);
    	std::memset(to,0,sizeof to);
    	tot=etot;etot=0;
    	for(R int i=1;i<=tot;i++)if(scc[e[i].from]!=scc[e[i].to])
    		add(scc[e[i].from],scc[e[i].to],0),in[scc[e[i].to]]++;
    	for(R int i=1;i<=scccnt;i++)
    		if(!vis[i]) dfs(i);
    	R LL ans=0,mod=1e9+7;
    	for(R int i=1;i<=n;i++)
    		ans+=(1ll*(sccmaxid[scc[i]]-sccminid[scc[i]]+1)*i)%mod,
    		ans%=mod;
    	std::printf("%lld",ans);
    	return 0;
    }
    
  • 相关阅读:
    linux进程cpu使用率过高分析与排查
    重启服务器后keepalived,vip找不到
    linux五种IO模型
    redis为什么单线程这么快?
    nginx为什么比apache快?
    redis高可用,主从,哨兵,集群
    git合并远端commit
    查看cpu和内存
    CommitLog文件和ConsumeQueue在文件系统中的映射
    hadoop集群启动
  • 原文地址:https://www.cnblogs.com/suxxsfe/p/12527442.html
Copyright © 2011-2022 走看看