[BZOJ2253] [2010 Beijing wc] 종이 상자 쌓기(dp+bit+cdq 분리)
10035 단어 풀다dpbitcdq분치/전체2분
제목 설명
컨베이어 도어
풀다
최장 상승 서브 서열 + 3차원 편차 문제 누드 dp 사람마다 맞겠죠 O(n2)는 서열에 대해 cdq분치를 고려합니다. 매번 왼쪽 구간으로 오른쪽 구간을 x분치에 따라 업데이트하고 매번 y분치에 따라 정렬합니다. 그리고 z는 나무 모양 수조로 조회합니다. 주의해야 할 것은 여기는 모두 엄격합니다. 즉, 분치를 할 때 좌우 양쪽으로 구분된 점에서 x가 같지 않은 상황입니다.이렇게 하면 미리 처리한 다음에 선택점을 선택할 때 하면 됩니다. 그리고 갱신 순서는 반드시 왼쪽 구간으로 돌아가야 합니다. 왼쪽 구간이 오른쪽 구간에 미치는 영향을 처리하고 오른쪽 구간으로 돌아가야 합니다.
코드
#include
#include
#include
#include
#include
using namespace std;
#define N 300005
int A,Mod,n,LSH,ans;
int lsh[N],L[N],R[N],C[N],f[N],ch[N];
struct data{int x,y,z,id;}q[N],a[N],b[N];
int cmp(data a,data b)
{
return a.xx||(a.x==b.x&&a.yy)||(a.x==b.x&&a.y==b.y&&a.zint cmpy(data a,data b)
{
return a.yy;
}
void cover(int loc)
{
for (int i=loc;i<=LSH;i+=i&-i)
C[i]=0;
}
void add(int loc,int val)
{
for (int i=loc;i<=LSH;i+=i&-i)
C[i]=max(C[i],val);
}
int query(int loc)
{
int ans=0;
for (int i=loc;i>=1;i-=i&-i)
ans=max(ans,C[i]);
return ans;
}
void cdq(int l,int r)
{
if (q[l].x==q[r].x) return;
int mid=(l+r)>>1;
if (L[mid]!=l) mid=L[mid]-1;
else mid=R[mid];
cdq(l,mid);
int tot=0;
int pa=1,pb=1,acnt=0,bcnt=0;
for (int i=l;i<=mid;++i) a[++acnt]=q[i];
for (int i=mid+1;i<=r;++i) b[++bcnt]=q[i];
sort(a+1,a+acnt+1,cmpy);sort(b+1,b+bcnt+1,cmpy);
while (pb<=bcnt)
{
while (pa<=acnt&&a[pa].yy)
{
add(a[pa].z,f[a[pa].id]);
ch[++tot]=a[pa].z;
++pa;
}
f[b[pb].id]=max(f[b[pb].id],query(b[pb].z-1)+1);
++pb;
}
for (int i=1;i<=tot;++i) cover(ch[i]);
cdq(mid+1,r);
}
int main()
{
scanf("%d%d%d",&A,&Mod,&n);q[0].z=1;
for (int i=1;i<=n;++i)
{
q[i].x=(long long)q[i-1].z*A%Mod,q[i].y=(long long)q[i].x*A%Mod;
q[i].z=(long long)q[i].y*A%Mod;
lsh[++LSH]=q[i].x,lsh[++LSH]=q[i].y,lsh[++LSH]=q[i].z;
}
for (int i=1;i<=n;++i)
{
if (q[i].x>q[i].y) swap(q[i].x,q[i].y);
if (q[i].y>q[i].z) swap(q[i].y,q[i].z);
if (q[i].x>q[i].y) swap(q[i].x,q[i].y);
}
sort(lsh+1,lsh+LSH+1);LSH=unique(lsh+1,lsh+LSH+1)-lsh-1;
for (int i=1;i<=n;++i)
q[i].x=lower_bound(lsh+1,lsh+LSH+1,q[i].x)-lsh,
q[i].y=lower_bound(lsh+1,lsh+LSH+1,q[i].y)-lsh,
q[i].z=lower_bound(lsh+1,lsh+LSH+1,q[i].z)-lsh;
sort(q+1,q+n+1,cmp);
for (int i=1;i<=n;++i) q[i].id=i;
for (int i=1;i<=n;++i)
if (i==1||q[i].x!=q[i-1].x) L[i]=i;
else L[i]=L[i-1];
for (int i=n;i>=1;--i)
if (i==n||q[i].x!=q[i+1].x) R[i]=i;
else R[i]=R[i+1];
f[q[1].id]=1;
cdq(1,n);
for (int i=1;i<=n;++i) ans=max(ans,f[i]);
printf("%d
",ans);
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
낙곡 P1040 플러스 두 갈래 나무제목: n n n 개의 노드가 있는 두 갈래 나무는 노드마다 하나의 점수가 있고 모든 자나무에도 점수가 있다. 각 자나무의 점수 계산 방법은 다음과 같다.× 오른쪽에 있는 나무의 가산점인 ubtr의 뿌리 점수.sub...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.