luogu U33697 寻找宝藏 (cdq分治+dp)

Posted ressed

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了luogu U33697 寻找宝藏 (cdq分治+dp)相关的知识,希望对你有一定的参考价值。

一道比赛的题...

设f[i]是已经走到i号点的值。

先要给第四维离散化、然后去重

第一维排序,第二维cdq分治,第三维cdq分治,第四维树状数组,找到满足j(x,y,z,w)<=i(x,y,z,w)的j,给i统计答案就可以。

然后在做的时候可以直接统计左区间内部答案、统计左区间给右区间造成的答案,但是一定要在这两个做完以后再统计右区间内部的答案,因为用右区间的某个j去更新i时,那个j是会被前面的区间影响的

然后就被卡常了QAQ...分治里一定要写尽量少的sort啊...

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 #include<vector>
  5 #include<queue>
  6 #include<cmath>
  7 #include<ctime>
  8 #define LL long long int
  9 #define inf 0x3f3f3f3f
 10 #define lowbit(x) ((x)&(-(x)))
 11 using namespace std;
 12 const int maxn=80080,mod=998244353;
 13 
 14 LL rd(){
 15    LL x=0;char c=getchar();int neg=1;
 16    while(c<0||c>9){if(c==-) neg=-1;c=getchar();}
 17    while(c>=0&&c<=9) x=x*10+c-0,c=getchar();
 18    return x*neg;
 19 }
 20 
 21 struct Node{
 22     int x,y,z,w,i;
 23     LL v;bool b;
 24 }tmp1[maxn],tmp2[maxn],tmp3[maxn],arr1[maxn];
 25 int N,M,mv[maxn],fv[maxn];
 26 LL ma[maxn],fa[maxn];
 27 const int sizN=sizeof(Node);
 28 
 29 inline void change(int x,LL y,int z){
 30     if(z==0){
 31         while(x&&x<=M) ma[x]=mv[x]=0,x+=lowbit(x);
 32         return;
 33     }
 34     while(x&&x<=M){
 35         if(ma[x]<y) ma[x]=y,mv[x]=z;
 36         else if(ma[x]==y) mv[x]=(mv[x]+z)%mod;
 37         else break;
 38         x+=lowbit(x);
 39     }
 40 }
 41 inline LL querya(int x){
 42     LL re=0;while(x) re=max(re,ma[x]),x-=lowbit(x);return re;
 43 }
 44 inline int queryv(int x){
 45     int re=0;LL a=0;
 46     while(x){
 47         if(ma[x]>a) re=mv[x],a=ma[x];
 48         else if(ma[x]==a) re=(re+mv[x])%mod;
 49         x-=lowbit(x);
 50     }return re;
 51 }
 52 
 53 inline bool cmpw(Node a,Node b){return a.w<b.w;}
 54 inline bool cmpz(Node a,Node b){
 55     return a.z==b.z?cmpw(a,b):a.z<b.z;
 56 }
 57 inline bool cmpy(Node a,Node b){
 58     return a.y==b.y?cmpz(a,b):a.y<b.y;
 59 }
 60 inline bool cmpx(Node a,Node b){
 61     return a.x==b.x?cmpy(a,b):a.x<b.x;
 62 }
 63 
 64 void cdq2(int l,int r){
 65     if(l>=r) return;
 66     //printf("!%d %d
",l,r);
 67     int m=l+r>>1,p=l,q=m+1,t=l;
 68     cdq2(l,m);sort(tmp1+l,tmp1+m+1,cmpz);
 69     memcpy(tmp3+m+1,tmp1+m+1,sizN*(r-m));sort(tmp1+m+1,tmp1+r+1,cmpz);
 70     while(p<=m&&q<=r){
 71         if(tmp1[p].z<=tmp1[q].z){
 72             if(!tmp1[p].b){
 73                 change(tmp1[p].w,fa[tmp1[p].i],fv[tmp1[p].i]);
 74             }p++;
 75         }else{
 76             if(tmp1[q].b){
 77                 LL a=querya(tmp1[q].w)+tmp1[q].v;int v=queryv(tmp1[q].w);
 78                 if(v){
 79                     if(a>fa[tmp1[q].i]) fa[tmp1[q].i]=a,fv[tmp1[q].i]=v;
 80                     else if(a==fa[tmp1[q].i]) fv[tmp1[q].i]=(fv[tmp1[q].i]+v)%mod;
 81                 }
 82             }
 83             q++;
 84         }
 85     }while(q<=r){
 86         if(tmp1[q].b){
 87             LL a=querya(tmp1[q].w)+tmp1[q].v;int v=queryv(tmp1[q].w);
 88             if(v){
 89                 if(a>fa[tmp1[q].i]) fa[tmp1[q].i]=a,fv[tmp1[q].i]=v;
 90                 else if(a==fa[tmp1[q].i]) fv[tmp1[q].i]=(fv[tmp1[q].i]+v)%mod;
 91             }
 92         }
 93         q++;
 94     }for(int i=l;i<p;i++) change(tmp1[i].w,0,0);
 95     memcpy(tmp1+m+1,tmp3+m+1,sizN*(r-m));cdq2(m+1,r);
 96 }
 97 
 98 void cdq1(int l,int r){
 99     if(l>=r) return;
100     int m=l+r>>1,p=l,q=m+1,t=l;
101     cdq1(l,m);sort(arr1+l,arr1+m+1,cmpy);
102     memcpy(tmp2+m+1,arr1+m+1,sizN*(r-m));sort(arr1+m+1,arr1+r+1,cmpy);
103     while(p<=m&&q<=r){
104         if(arr1[p].y<=arr1[q].y){
105             tmp1[t]=arr1[p++];tmp1[t].b=0;
106         }else{
107             tmp1[t]=arr1[q++];tmp1[t].b=1;
108         }t++;
109     }while(p<=m) tmp1[t]=arr1[p++],tmp1[t++].b=0;
110     while(q<=r) tmp1[t]=arr1[q++],tmp1[t++].b=1;
111     cdq2(l,r);
112     memcpy(arr1+m+1,tmp2+m+1,sizN*(r-m));cdq1(m+1,r);
113 }
114 
115 int main(){
116     //freopen("xzbz.in","r",stdin);
117     int i,j,k;
118     N=rd(),M=rd();
119     for(i=1;i<=N;i++){
120         tmp1[i].i=i;tmp1[i].x=rd();tmp1[i].y=rd();
121         tmp1[i].z=rd();tmp1[i].w=rd();tmp1[i].v=rd();
122     }sort(tmp1+1,tmp1+N+1,cmpw);
123     for(i=1,j=0;i<=N;i++){
124         tmp2[i]=tmp1[i];
125         if(tmp1[i].w==tmp1[i-1].w) tmp2[i].w=j;
126         else tmp2[i].w=++j;
127     }M=j;
128     sort(tmp2+1,tmp2+N+1,cmpx);
129     for(i=1,j=0;i<=N;i++){
130         if(tmp2[i].x==tmp2[i-1].x&&tmp2[i].y==tmp2[i-1].y&&tmp2[i].z==tmp2[i-1].z&&tmp2[i].w==tmp2[i-1].w){
131             arr1[j].v=(arr1[j].v+tmp2[i].v)%mod;
132             fa[j]=arr1[j].v;
133         }else{
134             arr1[++j]=tmp2[i];arr1[j].i=j;
135             fa[j]=arr1[j].v;fv[j]=1;
136         }
137     }N=j;
138     cdq1(1,N);
139     LL a=0;int v=0;
140     for(i=1;i<=N;i++){
141         if(fa[i]>a) a=fa[i],v=fv[i];
142         else if(fa[i]==a) v=(v+fv[i])%mod;
143     }printf("%lld
%d",a,v);
144     return 0;
145 }

 

以上是关于luogu U33697 寻找宝藏 (cdq分治+dp)的主要内容,如果未能解决你的问题,请参考以下文章

Luogu 3810 & BZOJ 3262 陌上花开/三维偏序 | CDQ分治

Luogu1393动态逆序对(CDQ分治)

bzoj3672/luogu2305 购票 (运用点分治思想的树上cdq分治+斜率优化dp)

luogu3810 陌上花开 (cdq分治)

luogu P3157 [CQOI2011]动态逆序对(CDQ分治)

luogu 3810