把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

luogu P5025 [SNOI2017]炸弹

题面传送门
考试的时候想了2h写了个假做法意识到错以后20min切掉我是sb
首先这个东西肯定是一个图论问题,然后发现如果边\((x,y)\)表示\(x\)爆了\(y\)跟着爆那么缩点以后答案就是这个点拓扑下去的点个数。
然后前面这个线段树优化建图就好了。
一个点拓扑下去的个数显然可以bitset但是不是我们想要的。
考虑一个点爆了肯定是最后引爆一个区间而不会一个区间中间断一个点,所以一个点的答案区间相当于所有儿子的区间取并,这个可以\(O(n)\)做,然后时间复杂度就是\(O(nlogn)\)
code:

#include<bits/stdc++.h>
#define I inline
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define abs(x) ((x)>0?(x):-(x))
#define re register
#define ll long long
#define db double
#define lb long db
#define N 500000
#define M 1000000
#define mod 1000000007
#define eps (1e-4)
#define U unsigned int
#define it iterator
#define Gc() getchar() 
#define Me(x,y) memset(x,y,sizeof(x))
#define d(x,y) (n*(x-1)+(y))
using namespace std;
int n,m,k,x,W[M+5],Id[N+5<<2],scc[M+5],low[M+5],dfn[M+5],vis[M+5],st[M+5],sh,cnt,dh,in[M+5],L[M+5],R[M+5],pus;ll A[N+5],B[N+5],Ans;
struct yyy{int to,z;}tmp;queue<int> Q;
struct ljb{int head,h[M+5];yyy f[N*40+5];I void add(int x,int y){f[++head]=(yyy){y,h[x]};h[x]=head;}}s,G;
I void build(int l=1,int r=n,int now=1){if(l==r) {Id[now]=r;return;}Id[now]=++cnt;int m=l+r>>1;build(l,m,now<<1);build(m+1,r,now<<1|1);s.add(Id[now],Id[now<<1]);s.add(Id[now],Id[now<<1|1]);}
I void Query(int x,int y,int z,int l=1,int r=n,int now=1){if(x<=l&&r<=y) return s.add(z,Id[now]);int m=l+r>>1;x<=m&&(Query(x,y,z,l,m,now<<1),0);y>m&&(Query(x,y,z,m+1,r,now<<1|1),0);}
I void tarjan(int x){
	dfn[x]=low[x]=++dh;vis[x]=1;st[++sh]=x;yyy tmp;for(int i=s.h[x];i;i=tmp.z)tmp=s.f[i],dfn[tmp.to]?(vis[tmp.to]&&(low[x]=min(low[x],low[tmp.to]))):(tarjan(tmp.to),low[x]=min(low[x],low[tmp.to]));
	if(low[x]==dfn[x]){pus++;while(st[sh+1]^x) W[st[sh]]&&(L[pus]=min(L[pus],st[sh]),R[pus]=max(R[pus],st[sh])),scc[st[sh]]=pus,vis[st[sh--]]=0;}
}
int main(){
//	freopen("bomb.in","r",stdin);freopen("bomb.out","w",stdout);
	re int i,j;Me(L,0x3f);scanf("%d",&n);for(i=1;i<=n;i++)W[i]=1;cnt=n;build();for(i=1;i<=n;i++) scanf("%lld%lld",&A[i],&B[i]);for(i=1;i<=n;i++)Query(lower_bound(A+1,A+n+1,A[i]-B[i])-A,upper_bound(A+1,A+n+1,A[i]+B[i])-A-1,i);
	/*for(i=1;i<=n;i++){
		for(j=1;j<=n;j++) if(A[j]>=A[i]-B[i]&&A[j]<=A[i]+B[i])s.add(i,j);
	}*/
	for(i=1;i<=cnt;i++) !dfn[i]&&(tarjan(i),0);for(i=1;i<=cnt;i++){
		for(j=s.h[i];j;j=tmp.z) tmp=s.f[j],scc[tmp.to]^scc[i]&&(G.add(scc[tmp.to],scc[i]),in[scc[i]]++);
	}for(i=1;i<=pus;i++) !in[i]&&(Q.push(i),0);while(!Q.empty())for(x=Q.front(),Q.pop(),i=G.h[x];i;i=tmp.z) tmp=G.f[i],in[tmp.to]--,L[tmp.to]=min(L[x],L[tmp.to]),R[tmp.to]=max(R[tmp.to],R[x]),!in[tmp.to]&&(Q.push(tmp.to),0);
	for(i=1;i<=n;i++)Ans=(Ans+1ll*(R[scc[i]]-L[scc[i]]+1)*i)%mod;printf("%lld\n",Ans);
}
posted @ 2021-08-17 18:10  275307894a  阅读(36)  评论(0编辑  收藏  举报
浏览器标题切换
浏览器标题切换end