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

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

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

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

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

 #include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
#include<cmath>
#include<ctime>
#define LL long long int
#define inf 0x3f3f3f3f
#define lowbit(x) ((x)&(-(x)))
using namespace std;
const int maxn=,mod=; LL rd(){
LL x=;char c=getchar();int neg=;
while(c<''||c>''){if(c=='-') neg=-;c=getchar();}
while(c>=''&&c<='') x=x*+c-'',c=getchar();
return x*neg;
} struct Node{
int x,y,z,w,i;
LL v;bool b;
}tmp1[maxn],tmp2[maxn],tmp3[maxn],arr1[maxn];
int N,M,mv[maxn],fv[maxn];
LL ma[maxn],fa[maxn];
const int sizN=sizeof(Node); inline void change(int x,LL y,int z){
if(z==){
while(x&&x<=M) ma[x]=mv[x]=,x+=lowbit(x);
return;
}
while(x&&x<=M){
if(ma[x]<y) ma[x]=y,mv[x]=z;
else if(ma[x]==y) mv[x]=(mv[x]+z)%mod;
else break;
x+=lowbit(x);
}
}
inline LL querya(int x){
LL re=;while(x) re=max(re,ma[x]),x-=lowbit(x);return re;
}
inline int queryv(int x){
int re=;LL a=;
while(x){
if(ma[x]>a) re=mv[x],a=ma[x];
else if(ma[x]==a) re=(re+mv[x])%mod;
x-=lowbit(x);
}return re;
} inline bool cmpw(Node a,Node b){return a.w<b.w;}
inline bool cmpz(Node a,Node b){
return a.z==b.z?cmpw(a,b):a.z<b.z;
}
inline bool cmpy(Node a,Node b){
return a.y==b.y?cmpz(a,b):a.y<b.y;
}
inline bool cmpx(Node a,Node b){
return a.x==b.x?cmpy(a,b):a.x<b.x;
} void cdq2(int l,int r){
if(l>=r) return;
//printf("!%d %d\n",l,r);
int m=l+r>>,p=l,q=m+,t=l;
cdq2(l,m);sort(tmp1+l,tmp1+m+,cmpz);
memcpy(tmp3+m+,tmp1+m+,sizN*(r-m));sort(tmp1+m+,tmp1+r+,cmpz);
while(p<=m&&q<=r){
if(tmp1[p].z<=tmp1[q].z){
if(!tmp1[p].b){
change(tmp1[p].w,fa[tmp1[p].i],fv[tmp1[p].i]);
}p++;
}else{
if(tmp1[q].b){
LL a=querya(tmp1[q].w)+tmp1[q].v;int v=queryv(tmp1[q].w);
if(v){
if(a>fa[tmp1[q].i]) fa[tmp1[q].i]=a,fv[tmp1[q].i]=v;
else if(a==fa[tmp1[q].i]) fv[tmp1[q].i]=(fv[tmp1[q].i]+v)%mod;
}
}
q++;
}
}while(q<=r){
if(tmp1[q].b){
LL a=querya(tmp1[q].w)+tmp1[q].v;int v=queryv(tmp1[q].w);
if(v){
if(a>fa[tmp1[q].i]) fa[tmp1[q].i]=a,fv[tmp1[q].i]=v;
else if(a==fa[tmp1[q].i]) fv[tmp1[q].i]=(fv[tmp1[q].i]+v)%mod;
}
}
q++;
}for(int i=l;i<p;i++) change(tmp1[i].w,,);
memcpy(tmp1+m+,tmp3+m+,sizN*(r-m));cdq2(m+,r);
} void cdq1(int l,int r){
if(l>=r) return;
int m=l+r>>,p=l,q=m+,t=l;
cdq1(l,m);sort(arr1+l,arr1+m+,cmpy);
memcpy(tmp2+m+,arr1+m+,sizN*(r-m));sort(arr1+m+,arr1+r+,cmpy);
while(p<=m&&q<=r){
if(arr1[p].y<=arr1[q].y){
tmp1[t]=arr1[p++];tmp1[t].b=;
}else{
tmp1[t]=arr1[q++];tmp1[t].b=;
}t++;
}while(p<=m) tmp1[t]=arr1[p++],tmp1[t++].b=;
while(q<=r) tmp1[t]=arr1[q++],tmp1[t++].b=;
cdq2(l,r);
memcpy(arr1+m+,tmp2+m+,sizN*(r-m));cdq1(m+,r);
} int main(){
//freopen("xzbz.in","r",stdin);
int i,j,k;
N=rd(),M=rd();
for(i=;i<=N;i++){
tmp1[i].i=i;tmp1[i].x=rd();tmp1[i].y=rd();
tmp1[i].z=rd();tmp1[i].w=rd();tmp1[i].v=rd();
}sort(tmp1+,tmp1+N+,cmpw);
for(i=,j=;i<=N;i++){
tmp2[i]=tmp1[i];
if(tmp1[i].w==tmp1[i-].w) tmp2[i].w=j;
else tmp2[i].w=++j;
}M=j;
sort(tmp2+,tmp2+N+,cmpx);
for(i=,j=;i<=N;i++){
if(tmp2[i].x==tmp2[i-].x&&tmp2[i].y==tmp2[i-].y&&tmp2[i].z==tmp2[i-].z&&tmp2[i].w==tmp2[i-].w){
arr1[j].v=(arr1[j].v+tmp2[i].v)%mod;
fa[j]=arr1[j].v;
}else{
arr1[++j]=tmp2[i];arr1[j].i=j;
fa[j]=arr1[j].v;fv[j]=;
}
}N=j;
cdq1(,N);
LL a=;int v=;
for(i=;i<=N;i++){
if(fa[i]>a) a=fa[i],v=fv[i];
else if(fa[i]==a) v=(v+fv[i])%mod;
}printf("%lld\n%d",a,v);
return ;
}

luogu4849 寻找宝藏 (cdq分治+dp)的更多相关文章

  1. BZOJ 2225: [Spoj 2371]Another Longest Increasing (CDQ分治+dp)

    题面 Description 给定N个数对(xi, yi),求最长上升子序列的长度.上升序列定义为{(xi, yi)}满足对i<j有xi<xj且yi<yj. Input Output ...

  2. [BZOJ4700]适者(CDQ分治+DP/李超线段树)

    如果没有秒杀,就是经典的国王游戏问题,按t/a从小到大排序即可. 考虑删除两个数i<j能给答案减少的贡献:S[i]*T[i]+P[i-1]*A[i]-A[i]+S[j]*T[j]+P[j-1]* ...

  3. cdq分治(偏序)

    偏序问题: https://www.luogu.org/blog/Owencodeisking/post-xue-xi-bi-ji-cdq-fen-zhi-hu-zheng-ti-er-fen 优质题 ...

  4. 51Nod1376 (dp + BIT // cdq分治)

    https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1376 求LIS的数量. 乍一看觉得还是dp,仔细一看确实可以用dp做. ...

  5. HDU5322 Hope(DP + CDQ分治 + NTT)

    题目 Source http://acm.hdu.edu.cn/showproblem.php?pid=5322 Description Hope is a good thing, which can ...

  6. 【BZOJ-1492】货币兑换Cash DP + 斜率优化 + CDQ分治

    1492: [NOI2007]货币兑换Cash Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 3396  Solved: 1434[Submit][Sta ...

  7. 斜率dp cdq 分治

    f[i] = min { f[j] + sqr(a[i] - a[j]) } f[i]= min { -2 * a[i] * a[j] + a[j] * a[j] + f[j] } + a[i] * ...

  8. bzoj 2244 [SDOI2011]拦截导弹(DP+CDQ分治+BIT)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2244 [题意] 给定n个二元组,求出最长不上升子序列和各颗导弹被拦截的概率. [思路] ...

  9. BZOJ 2726: [SDOI2012]任务安排( dp + cdq分治 )

    考虑每批任务对后面任务都有贡献, dp(i) = min( dp(j) + F(i) * (T(i) - T(j) + S) ) (i < j <= N)  F, T均为后缀和. 与j有关 ...

随机推荐

  1. 【JVM.5】类文件结构

    鲁迅曾经说过:代码编译的结构从本地机器码转变为字节码,是存储格式发展的一小步,确是编程语言发展的一大步. 一.无关性的基石 Java设计者在最初就承诺过“In the future, we will ...

  2. Linux下monit进程管理操作梳理

    Monit对运维人员来说可谓神器,它是一款功能非常丰富的进程.文件.目录和设备的监测工具,用于Unix平台.它可以自动修复那些已经停止运作的程序,特使适合处理那些由于多种原因导致的软件错误.Monit ...

  3. Linux内核分析作业 NO.8 完结撒花~~~

    进程的切换和系统的一般执行过程 于佳心  原创作品转载请注明出处  <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-10000 ...

  4. Java web错误总结~

    1.java程序中没有错,但是项目上面显示一个红叉的解决办法 错误信息: 报Description  Resource Path Location Type Java compiler level d ...

  5. 第六次作业-my Backlog

    杨灵超小组 My  Backlog                                小学生四则运算自动生成(Backlog) ID Name IMP EST How   to Demo ...

  6. 探秘Java中的String、StringBuilder以及StringBuffer(转载)

    探秘Java中String.StringBuilder以及StringBuffer 相信String这个类是Java中使用得最频繁的类之一,并且又是各大公司面试喜欢问到的地方,今天就来和大家一起学习一 ...

  7. Activiti的BPMN演示工具

    场景是这样的:产品经理不懂技术,又不想安装Java以及Eclipse(需要安装Activiti BPMN Designer的插件). 这两天解决.bpmn的解析(BPMNParser)时顺带找到一个顺 ...

  8. JavaScript解决一个带验证的Form两个Submit事件(一个页面保持不动【AJAX实现】,一个页面提交并跳转)的场景

    <form class="form-horizontal" action="/biz/patent/edit" method="post&quo ...

  9. C语言ODBC数据库操作

    今天我们来介绍一下C语言操作数据库的方法,这里我们使用的是ODBC方式.环境是WIN7+VC6.其他环境也差不多,具体情况具体分析. 首先是环境的配置以及数据源的添加.这里就不去解释了,相关资料网上有 ...

  10. 数组操作方法(包括es5)

    //push(); 定义:可以可向数组的末尾添加一个或更多元素,并返回新的长度. 方法:push(); 语法:数组.push(新元素1,新元素2,....,新元素x) 返回值:把指定的值添加到数组后的 ...