bzoj2253(DP+CDQ分治)

题目链接

https://www.lydsy.com/JudgeOnline/problem.php?id=2253

题解

看错题意坑了好久。。

朴素的 $DP$ 只能做到 $O(n^2)$ 的,要能够快速确定那个点是小于当前点。。

这个可以用 $CDQ$ 分治,由于在维护当前点时必须把前面的点都维护好,所以在分治的时候得先分治左区间,再整体转移影响,再分治右区间。。(感觉好麻烦

然后有个坑点是题目要求严格小于,所以在取 $mid$ 的时候得保证 $mid$ 两侧的 $x$ 是不同的。。




代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
/**
*         ┏┓    ┏┓
*         ┏┛┗━━━━━━━┛┗━━━┓
*         ┃       ┃  
*         ┃   ━    ┃
*         ┃ >   < ┃
*         ┃       ┃
*         ┃... ⌒ ...  ┃
*         ┃ ┃
*         ┗━┓ ┏━┛
*          ┃ ┃ Code is far away from bug with the animal protecting          
*          ┃ ┃ 神兽保佑,代码无bug
*          ┃ ┃           
*          ┃ ┃       
*          ┃ ┃
*          ┃ ┃           
*          ┃ ┗━━━┓
*          ┃ ┣┓
*          ┃ ┏┛
*          ┗┓┓┏━━━━━━━━┳┓┏┛
*           ┃┫┫ ┃┫┫
*           ┗┻┛ ┗┻┛
*/

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<queue>
#include<map>
#include<stack>
#include<cmath>
#include<set>
#include<bitset>
#include<assert.h>
#define inc(i,l,r) for(int i=l;i<=r;i++)
#define dec(i,l,r) for(int i=l;i>=r;i--)
#define link(x) for(edge *j=h[x];j;j=j->next)
#define mem(a) memset(a,0,sizeof(a))
#define ll long long
#define eps 1e-6
#define succ(x) (1<<x)
#define lowbit(x) (x&(-x))
#define sqr(x) ((x)*(x))
#define NM 50005
#define nm 5000005
#define pi 3.1415926535897931
using namespace std;
const int inf=1e9;
ll read(){
ll x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
return f*x;
}






struct P{
int x,y,z,id;
bool operator<(const P&o)const{return x<o.x||(x==o.x&&(y<o.y||(y==o.y&&z<o.z)));}
}a[NM];
bool cmp(P a,P b){return a.y<b.y||(a.y==b.y&&a.x<b.x);}
int n,ans,d[NM],c[NM],b[NM],tot;
ll _t,_x,_y;

int pro(){return (_t*=_x)%=_y;}
void add(int x,int t){for(;x<=n;x+=lowbit(x))c[x]=max(c[x],t);}
int sum(int x,int s=0){for(;x;x-=lowbit(x))s=max(s,c[x]);return s;}
void clr(int x){for(;x<=n&&c[x];x+=lowbit(x))c[x]=0;}

void cdq(int l,int r){
if(l==r)return;
int mid=-1,cnt=l;
inc(i,l,r-1)if(a[i].x<a[i+1].x&&abs(i-(l+r)/2)<abs(mid-(l+r)/2))mid=i;
if(mid==-1)return;
cdq(l,mid);
sort(a+l,a+mid+1,cmp);sort(a+mid+1,a+r+1,cmp);
for(int x=l,y=mid+1;x<=mid||y<=r;)if(x<=mid&&(y>r||(a[x].y<a[y].y))){
add(a[x].z,d[a[x].id]);x++;
}else{
d[a[y].id]=max(d[a[y].id],sum(a[y].z-1)+1);y++;
}
inc(i,l,mid)clr(a[i].z);
sort(a+mid+1,a+r+1);
cdq(mid+1,r);
}

int main(){
_x=read();_y=read();n=read();_t=1;_x%=_y;
inc(i,1,n){
a[i].x=pro(),a[i].y=pro(),a[i].z=pro();
if(a[i].x>a[i].y)swap(a[i].x,a[i].y);
if(a[i].x>a[i].z)swap(a[i].x,a[i].z);
if(a[i].y>a[i].z)swap(a[i].y,a[i].z);
b[++tot]=a[i].z;
}
sort(b+1,b+1+tot);tot=unique(b+1,b+1+tot)-b-1;
inc(i,1,n)a[i].z=lower_bound(b+1,b+1+tot,a[i].z)-b;
inc(i,1,n)d[i]=1;
sort(a+1,a+1+n);
inc(i,1,n)a[i].id=i;
//inc(i,1,n)printf("%d %d %d\n",a[i].x,a[i].y,a[i].z);
cdq(1,n);
//inc(i,1,n)printf("%d ",d[i]);putchar('\n');
inc(i,1,n)ans=max(ans,d[i]);
printf("%d\n",ans);
return 0;
}