好長時間沒寫博客了...春季學期的日記彷佛是沒怎麼寫, 回頭寫個總結反思放上來...
這個題首先一看就是圖論題, 看兩眼就是須要數據結構優化的圖論題, 並且確定是用線段樹. 看三眼發現須要tarjan求一下強連通份量.
看四眼看出來引爆一個炸彈, 最終可以引爆的全部炸彈必定是一個連續區間內的全部炸彈, 而後就發現只須要求每一個炸彈可以引爆的編號最小和最大的炸彈
也就是從強連通份量縮點以後的DAG上算一下每一個SCC可以到達的編號最小/最大的炸彈.
思路清晰天然, 是個不錯的題.數據結構
#include <cstdio> #include <vector> #include <algorithm> using namespace std; typedef long long ll; const int maxn=1000005; struct edge{ int to, next; }lst[maxn*40];int len=1; int first[maxn]; void addedge(int a,int b){ lst[len].to=b; lst[len].next=first[a]; first[a]=len++; } int N; ll X[maxn], R[maxn]; int left[maxn], right[maxn]; struct seg{ static int ID; int l,r,id; seg* ch[2]; seg(int a,int b):l(a),r(b){ if(a==b)id=a; else id=++ID; ch[0]=ch[1]=0; } }; int seg::ID=1; void build(seg* &root, int L, int R){ root = new seg(L,R); if(L==R)return; build(root->ch[0],L,(L+R)>>1); build(root->ch[1],((L+R)>>1)+1,R); addedge(root->id, root->ch[0]->id); addedge(root->id, root->ch[1]->id); } void add(seg* rt, int from, int L, int R){ if(L <= rt->l && rt->r <= R){ if(from!=rt->id)addedge(from, rt->id); }else{ int mid=(rt->l+rt->r)>>1; if(L<=mid)add(rt->ch[0],from,L,R); if(R>mid)add(rt->ch[1],from,L,R); } } int dfn[maxn], low[maxn], T; int stk[maxn],top=0; bool ins[maxn]; vector<int> scc[maxn];int cntscc=0; int belong[maxn]; void dfs(int x){ dfn[x]=low[x]=++T; stk[top++]=x;ins[x]=true; for(int pt=first[x];pt;pt=lst[pt].next){ if(!dfn[lst[pt].to]){ dfs(lst[pt].to); if(low[lst[pt].to]<low[x])low[x]=low[lst[pt].to]; }else if(ins[lst[pt].to] && dfn[lst[pt].to]<low[x])low[x]=dfn[lst[pt].to]; } if(low[x] == dfn[x]){ ++cntscc; do{ scc[cntscc].push_back(stk[--top]); belong[stk[top]]=cntscc; ins[stk[top]]=false; }while(stk[top]!=x); } } void tarjan(){ for(int i=1;i<=N;++i){ if(!dfn[i])dfs(i); } } int lo[maxn], hi[maxn], vis[maxn]; void DFS(int x){ vis[x]=1; for(vector<int>::iterator p=scc[x].begin();p!=scc[x].end();++p){ if(1<=(*p) &&(*p)<=N){ if((*p)>hi[x])hi[x]=*p; if((*p)<lo[x])lo[x]=*p; } for(int pt=first[*p];pt;pt=lst[pt].next){ int y=belong[lst[pt].to]; if(!vis[y]){ DFS(y); } if(hi[y]>hi[x])hi[x]=hi[y]; if(lo[y]<lo[x])lo[x]=lo[y]; } } } void dp(){ for(int i=1;i<=cntscc;++i){ lo[i]=N+1;hi[i]=0; } for(int i=1;i<=cntscc;++i){ if(!vis[i])DFS(i); } } int main(){ scanf("%d",&N); for(int i=1;i<=N;++i){ scanf("%lld%lld",X+i, R+i); } for(int i=1;i<=N;++i){ left[i]=lower_bound(X+1,X+N+1, X[i]-R[i])-X; right[i]=upper_bound(X+1, X+N+1, X[i]+R[i])-X-1; } seg::ID=N; seg *root; build(root, 1, N);//while(1); for(int i=1;i<=N;++i){ add(root,i,left[i],right[i]); } tarjan(); dp(); int ans=0; int mod=(int)(1e9+7); for(int i=1;i<=N;++i){ ans = (ans + i * 1ll * (hi[belong[i]]-lo[belong[i]]+1))%mod; } printf("%d\n",ans); return 0; }