好长时间没写博客了...春季学期的日记彷佛是没怎么写, 回头写个总结反思放上来...
这个题首先一看就是图论题, 看两眼就是须要数据结构优化的图论题, 并且确定是用线段树. 看三眼发现须要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; }