[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 }
View Code

 

posted @ 2022-04-12 19:46  PYWBKTDA  阅读(79)  评论(0编辑  收藏  举报