P5025-[SNOI2017]炸弹【tarjan,线段树优化建图】
生活随笔
收集整理的這篇文章主要介紹了
P5025-[SNOI2017]炸弹【tarjan,线段树优化建图】
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
正題
題目鏈接:https://www.luogu.com.cn/problem/P5025
題目大意
.nnn個炸彈,每個在xxx位置處,范圍為rrr。定義fif_ifi?表示第iii個炸彈爆炸能連鎖的炸彈數,要求輸出∑i=1nfi?i\sum_{i=1}^nf_i*ii=1∑n?fi??i
解題思路
將每個炸彈可以炸開的炸彈連邊,然后每個強連通分量之間可以互相炸,然后在tarjantarjantarjan時統計這個強連通分量內的炸彈炸的范圍li,ril_i,r_ili?,ri?。然后用dfsdfsdfs在DAGDAGDAG上更新即可。
但是這樣建的邊是n2n^2n2級別的,顯然不能通過本題,因為建的邊都是在一個區間內,用線段樹優化建邊,每個節點代表這個這個節點能夠通向連向的區間點,然后優化為nlog?nn\log nnlogn的級別。
codecodecode
#include<cstdio> #include<cstring> #include<algorithm> #include<stack> #define ll long long using namespace std; const ll N=2e6+10,XJQ=1e9+7; struct node{ll to,from,next; }a[N*15]; ll n,tot,num,cnt,ans; ll lso[N],rso[N],dfn[N],low[N]; ll l[N],r[N],ls[N],fa[N],w[N],rr[N]; stack<int> S; bool v[N]; void addl(ll x,ll y){a[++tot].to=y;a[tot].from=x;a[tot].next=ls[x];ls[x]=tot;return; } ll build(ll x,ll l,ll r){if(l==r)return l;if(!x)x=++cnt;ll mid=(l+r)>>1;lso[x]=build(lso[x],l,mid);rso[x]=build(rso[x],mid+1,r);addl(x,lso[x]);addl(x,rso[x]);return x; } void change(ll x,ll L,ll R,ll l,ll r,ll pos){if(L==l&&R==r){addl(pos,x);return;}ll mid=(L+R)>>1;if(r<=mid)change(lso[x],L,mid,l,r,pos);else if(l>mid)change(rso[x],mid+1,R,l,r,pos);else change(lso[x],L,mid,l,mid,pos),change(rso[x],mid+1,R,mid+1,r,pos);return; } void tarjan(ll x){dfn[x]=low[x]=++num;v[x]=1;S.push(x);for(ll i=ls[x];i;i=a[i].next){ll y=a[i].to;if(!dfn[y]){tarjan(y);low[x]=min(low[x],low[y]);}else if(v[y]) low[x]=min(low[x],dfn[y]);}if(dfn[x]==low[x]){ll y;do{y=S.top();v[y]=0;fa[y]=x;l[x]=min(l[x],l[y]);r[x]=max(r[x],r[y]);S.pop();}while(x!=y);}return; } void dfs(ll x){v[x]=1;for(ll i=ls[x];i;i=a[i].next){ll y=a[i].to;if(!v[y])dfs(y);l[x]=min(l[x],l[y]);r[x]=max(r[x],r[y]);}return; } int main() {scanf("%lld",&n);for(ll i=1;i<=n;i++)scanf("%lld%lld",&w[i],&rr[i]);cnt=n;build(0,1,n);memset(l,127,sizeof(l));w[n+1]=2147483647;for(ll i=1;i<=n;i++){ll L=lower_bound(w+1,w+1+n,w[i]-rr[i])-w;ll R=upper_bound(w+1,w+1+n,w[i]+rr[i])-w-1;change(n+1,1,n,L,R,i);l[i]=L;r[i]=R;}for(ll i=1;i<=cnt;i++)if(!dfn[i])tarjan(i);ll TOT=tot;tot=0;memset(ls,0,sizeof(ls));for(ll i=1;i<=TOT;i++){ll x=a[i].from,y=a[i].to;if(fa[x]==fa[y])continue;addl(fa[a[i].from],fa[a[i].to]);}memset(v,0,sizeof(v));for(ll i=1;i<=cnt;i++)if(fa[i]==i)dfs(i);for(ll i=1;i<=n;i++)ans=(ans+(r[fa[i]]-l[fa[i]]+1)*i%XJQ)%XJQ;printf("%lld",ans);return 0; }總結
以上是生活随笔為你收集整理的P5025-[SNOI2017]炸弹【tarjan,线段树优化建图】的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 豪华车市场酣战,月破4万的理想能过BBA
- 下一篇: P2472-[SCOI2007]蜥蜴【网