题解 CF167D【Wizards and Roads】
xtx1092515503 · · 题解
CF167D Wizards and Roads
首先我们看向奇奇怪怪的生成方式。只有
为什么呢?因为它保证
进而我们将所有点按
考虑令
相反,若
但是需要注意的是,
那么我们总结一下,令
同样的讨论亦适用于
考虑这个关系。自己画一个单调栈玩玩的话,会发现其直接就是一棵笛卡尔树。
那么我们的思路到这时已经很清晰了,即求出区间
这听上去是个很复杂的问题。但是我们一开始就声明了我们的点具有随机的性质,进而
具体而言,我们考虑
代码:
#include<bits/stdc++.h>
using namespace std;
const int mod=1e9+9;
int n,q,K,_a,_b,_c,_d,a[100100],b[100100];
int ch[100100][2],rt,f[100100][2],g[100100][2],tp,stk[100100];
pair<int,int>p[100100];
void dfs(int x){
for(int i=0,y;i<2;i++)if(y=ch[x][i]){
dfs(y);
f[x][1]=max(f[x][1]+max(f[y][0],f[y][1]),f[x][0]+f[y][0]+1);
f[x][0]=f[x][0]+max(f[y][0],f[y][1]);
}
}
#define lson ch[x][0]
#define rson ch[x][1]
void dfs(int x,int l,int r,int L,int R){
g[x][0]=0xc0c0c0c0,g[x][1]=0;
if(!x||l>R||r<L)return;
if(R<x){dfs(lson,l,x-1,L,R),g[x][0]=g[lson][0],g[x][1]=g[lson][1];return;}
if(L>x){dfs(rson,x+1,r,L,R),g[x][0]=g[rson][0],g[x][1]=g[rson][1];return;}
if(L<=l&&r<=R){g[x][0]=f[x][0],g[x][1]=f[x][1];return;}
g[x][0]=g[x][1]=0;
int y;
y=lson;dfs(y,l,x-1,L,R);
g[x][1]=max(g[x][1]+max(g[y][0],g[y][1]),g[x][0]+g[y][0]+1);
g[x][0]=g[x][0]+max(g[y][0],g[y][1]);
y=rson;dfs(y,x+1,r,L,R);
g[x][1]=max(g[x][1]+max(g[y][0],g[y][1]),g[x][0]+g[y][0]+1);
g[x][0]=g[x][0]+max(g[y][0],g[y][1]);
}
int main(){
scanf("%d%d",&n,&K);
for(int i=1;i<=K;i++)scanf("%d%d",&p[i].first,&p[i].second);
scanf("%d%d%d%d",&_a,&_b,&_c,&_d);
for(int i=K+1;i<=n;i++)
p[i]=make_pair((1ll*p[i-1].first*_a+_b)%mod,(1ll*p[i-1].second*_c+_d)%mod);
sort(p+1,p+n+1,[](pair<int,int>x,pair<int,int>y){return x.second<y.second;});
for(int i=1;i<=n;i++)p[i].second=i;
sort(p+1,p+n+1);
for(int i=1;i<=n;i++)a[i]=p[i].first,b[i]=p[i].second;
// for(int i=1;i<=n;i++)printf("%d %d\n",a[i],b[i]);
for(int i=1;i<=n;i++){
while(tp&&b[stk[tp]]<b[i])ch[i][0]=stk[tp--];
if(tp)ch[stk[tp]][1]=i;stk[++tp]=i;
}
rt=stk[1],dfs(rt);
scanf("%d",&q);
for(int i=1,l,r;i<=q;i++){
scanf("%d%d",&l,&r);
l=lower_bound(a+1,a+n+1,l)-a;
r=upper_bound(a+1,a+n+1,r)-a-1;
dfs(rt,1,n,l,r);
printf("%d\n",max(g[rt][0],g[rt][1]));
}
return 0;
}