[loj522]绯色 IOI(危机)
将炸弹按坐标排序并建图,其中$(i,j)\in E$当且仅当$|x_{i}-x_{j}|\le r_{i}$
性质:$\forall i\in[1,n],\{j\mid (i,j)\in E\}$和$\{j\mid i能到达j\}$均构成连续区间
前者显然,后者考虑第一次跨过该点时根据前者即可到达该点
结论:$\forall k\in [1,n],|\{i\mid i能到达k\}|\sim o(\log R)$(其中$R=\max r_{i}$)
根据对称性,不妨仅考虑在$k$右侧的$i$,并依次记为$a_{1}<a_{2}<...<a_{m}$
引理1:$\forall i\in [1,m],d(a_{i},k)$严格单调递增(关于$d$的定义参考题面)
根据性质,$a_{i+1}$可以到达$a_{i}$,将该路径与$a_{i}$到$k$的路径拼接即可(若有重复点即成环)
引理2:$\forall x能到达y,d(x,y)\sim o(\log R)$
假设$x$到$y$的最长路径为$a_{1},a_{2},...,a_{m}$,显然$\forall i\in [1,m-2],d(a_{i},a_{i+2})=3$
结合题中条件,有$(a_{i},a_{i+2})\in E$,进而对$a_{i+1}$的位置分类讨论:
1.若$a_{i+1}$与$a_{i+2}$在$a_{i}$的两侧,则$a_{i}$与$a_{i+1}$相互可达,矛盾
2.若$a_{i}$与$a_{i+2}$在$a_{i+1}$的两侧,则有$\begin{cases}R_{a_{i+2}}<R_{a_{i+1}}&\\R_{a_{i+1}}+R_{a_{i+2}}< R_{a_{i}}\end{cases}$
前者是因为$(a_{i+2},a_{i+1})\not\in E$,后者结合$(a_{i+1},a_{i})\not\in E$且$(a_{i},a_{i+2})\in E$即可得到
3.若$a_{i}$与$a_{i+1}$在$a_{i+2}$的两侧,则有$2R_{a_{i+2}}<R_{a_{i}}$(原因类似)
综上,均有$R_{a_{i+2}}<\frac{R_{i}}{2}$,进而$o(\log R)$次后$R=0$,路径必然结束
结合上述两个引理,结论显然成立
综上分析,考虑依次执行以下步骤:
1.二分出$\{j\mid (i,j)\in E\}$对应区间(优化建图)并拓扑排序
2.记$\{j\mid i能到达j\}$对应区间为$[L_{i},R_{i}]$,转移即$\begin{cases}L_{i}=\min_{(i,j)\in E}L_{j}\\R_{i}=\max_{(i,j)\in E}R_{j}\end{cases}$(倒序枚举拓扑序)
3.定义$f_{i}$表示以$i$为结尾的答案,转移即$\forall j\in [L_{i},R_{i}],f_{i}+F(v_{i},v_{j})\rightarrow f_{j}$(正序枚举拓扑序)
时间复杂度为$o(n\log R)$,可以通过
另外,跳过第2步直接搜索$\{j\mid i能到达j\}$转移$f$会多一个$\log$

1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 300005 4 #define mod 998244353 5 #define ll long long 6 struct Data{ 7 ll x,r;int v,id; 8 bool operator < (const Data &k)const{ 9 return x<k.x; 10 } 11 }a[N]; 12 int n,l[N],r[N],dfn[N],deg[N],L[N],R[N];ll f[N]; 13 int F(int x,int y){ 14 return ((x^y)+(ll)x*y)%mod; 15 } 16 int main(){ 17 scanf("%d",&n); 18 for(int i=1;i<=n;i++)scanf("%lld",&a[i].x); 19 for(int i=1;i<=n;i++)scanf("%lld",&a[i].r); 20 for(int i=1;i<=n;i++)scanf("%d",&a[i].v); 21 for(int i=1;i<=n;i++)a[i].id=i;sort(a+1,a+n+1); 22 for(int i=1;i<=n;i++){ 23 l[i]=lower_bound(a+1,a+n+1,Data{a[i].x-a[i].r,0,0,0})-a; 24 r[i]=upper_bound(a+1,a+n+1,Data{a[i].x+a[i].r,0,0,0})-a-1; 25 for(int j=l[i];j<=r[i];j++) 26 if (j!=i)deg[j]++; 27 } 28 for(int i=1;i<=n;i++) 29 if (!deg[i])dfn[++dfn[0]]=i; 30 for(int i=1;i<=n;i++) 31 for(int j=l[dfn[i]];j<=r[dfn[i]];j++) 32 if ((j!=dfn[i])&&(--deg[j]==0))dfn[++dfn[0]]=j; 33 for(int i=1;i<=n;i++)L[i]=R[i]=i; 34 for(int i=n;i;i--){ 35 int x=dfn[i]; 36 for(int j=l[x];j<=r[x];j++) 37 if (j!=x)L[x]=min(L[x],L[j]),R[x]=max(R[x],R[j]); 38 } 39 for(int i=1;i<=n;i++){ 40 int x=dfn[i]; 41 for(int j=L[x];j<=R[x];j++) 42 if (j!=x)f[a[j].id]=max(f[a[j].id],f[a[x].id]+F(a[x].v,a[j].v)); 43 } 44 for(int i=1;i<=n;i++)printf("%lld\n",f[i]); 45 return 0; 46 }