【BZOJ】1537: [POI2005]Aut- The Bus

【算法】DP+线段树求区间max(二维偏序)

【题解】

状态转移方程:f[i]=max(f[j]+v[i]),x[j]<x[i]&&y[j]<y[i]。

观察j的条件限制显然是二维偏序求最大值,套路化地离散化后一维排序+一维线段树即可解决。

最后在f[i]中找max,所以不用恢复原序。

复杂度O(n log n)。

#include<cstdio>
#include<cstring>
#include<cctype>
#include<algorithm>
using namespace std;
const int maxn=300010;
int f[maxn],n,m,k;
inline int max(int x,int y){return x>y?x:y;}
struct lshs{int x,ord;}ls[maxn];
struct cyc{int x,y,v;}a[maxn];
struct tree{int l,r,mx;}t[maxn*2];
bool cmps(cyc a,cyc b){return a.x<b.x||(a.x==b.x&&a.y<b.y);}
bool cmp(lshs a,lshs b){return a.x<b.x;}
int read()
{
    char c;int s=0,t=1;
    while(!isdigit(c=getchar()))if(c==‘-‘)t=-1;
    do{s=s*10+c-‘0‘;}while(isdigit(c=getchar()));
    return s*t;
}
void lsh(){
    for(int i=1;i<=k;i++)ls[i]=(lshs){a[i].x,i};
    sort(ls+1,ls+k+1,cmp);
    int p=0;
    for(int i=1;i<=k;i++)if(ls[i].x==ls[i-1].x)a[ls[i].ord].x=p;else a[ls[i].ord].x=++p;
    n=p;
    for(int i=1;i<=k;i++)ls[i]=(lshs){a[i].y,i};
    sort(ls+1,ls+k+1,cmp);
    p=0;
    for(int i=1;i<=k;i++)if(ls[i].x==ls[i-1].x)a[ls[i].ord].y=p;else a[ls[i].ord].y=++p;
    m=p;
}
void build(int k,int l,int r){
    t[k].l=l;t[k].r=r;
    if(l==r)return;
    int mid=(l+r)>>1;
    build(k<<1,l,mid);
    build(k<<1|1,mid+1,r);
}
void insert(int k,int x,int y){
    if(t[k].l==t[k].r){t[k].mx=max(t[k].mx,y);}
    else{
        int mid=(t[k].l+t[k].r)>>1;
        if(x<=mid)insert(k<<1,x,y);
        else insert(k<<1|1,x,y);
        t[k].mx=max(t[k<<1].mx,t[k<<1|1].mx);
    }
}
int find(int k,int l,int r){
    if(l<=t[k].l&&t[k].r<=r)return t[k].mx;
    else{
        int mid=(t[k].l+t[k].r)>>1,mx=0;
        if(l<=mid)mx=find(k<<1,l,r);
        if(r>mid)mx=max(mx,find(k<<1|1,l,r));
        return mx;
    }
}
int main(){
    n=read();m=read();k=read();
    for(int i=1;i<=k;i++){
        a[i].x=read();a[i].y=read();a[i].v=read();
    }
    lsh();
    sort(a+1,a+k+1,cmps);
    build(1,1,m);
    for(int i=1;i<=k;i++){
        f[i]=find(1,1,a[i].y)+a[i].v;
        insert(1,a[i].y,f[i]);
    }
    int ans=0;
    for(int i=1;i<=k;i++)ans=max(ans,f[i]);
    printf("%d",ans);
    return 0;
}

时间: 2024-10-08 03:04:18

【BZOJ】1537: [POI2005]Aut- The Bus的相关文章

【BZOJ】1529 [POI2005]ska Piggy banks

[算法](强连通分量)并查集 [题解] 1.用tarjan计算强连通分量并缩点,在新图中找入度为0的点的个数就是答案. 但是,会爆内存(题目内存限制64MB). 2.用并查集,最后从1到n统计fa[i]==i的数量即是答案. (tarjan) #include<cstdio> #include<algorithm> using namespace std; const int maxn=1000010; struct edge{int u,v,from;}e[maxn]; int

【BZOJ】3319: 黑白树

http://www.lydsy.com/JudgeOnline/problem.php?id=3319 题意:给一棵n节点的树(n<=1e6),m个操作(m<=1e6),每次操作有两种:1.查询u到根的第一条黑边的编号.2.将u到v的路径全部染成黑色 #include <cstdio> #include <cstring> #include <cmath> #include <string> #include <iostream>

【bzoj】4538: [Hnoi2016]网络

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=4538 维护一个数据结构支持对于一颗树的操作,需要支持: 1.对于树上的一条路径上的每个点上放一个值. 2.撤销某次操作的路劲放. 3.查询除了经过这个点的路径的最大值. 往一个路径上丢值相当于往不经过条路径的所有点上丢值. 用一个树链剖分即可维护,对于操作区间取反. 直接查询单点最大值即可. 为了维护单点最大值,线段树中的每一个点对应两个堆,用于维护插入誉删除. 防止爆空间,所以标记永久

【BZOJ】1821: [JSOI2010]Group 部落划分 Group(最小生成树+贪心)

http://www.lydsy.com:808/JudgeOnline/problem.php?id=1821 这题裸题. 本题要求最短距离最长,很明显,我们排序. 这里存在贪心,即我们把边权最小的全分给n个部落的内部,然后剩下的边最小的就是答案. 将边权较小的边分给k个部落,用并查集生成最小树,使得内部的边总是小于连到外部的边.然后分剩下k个点即可,剩下的k个点的那条边一定是部落之间最小的且最长的边. #include <cstdio> #include <cstring> #

【BZOJ】【3083】遥远的国度

树链剖分/dfs序 其实过了[BZOJ][4034][HAOI2015]T2以后就好搞了…… 链修改+子树查询+换根 其实静态树的换根直接树链剖分就可以搞了…… 因为其实只有一样变了:子树 如果root在x的子树中(以1为根dfs的时候),那么现在x的子树就变成了整个dfs序中,除去含有root的那个子树的剩下的部分,画个图大概就是这样:(红色部分为现在的子树) 我们发现,这种子树由于换根而产生变化的情况,仅当在以1为根时的树中,x是new_root的祖先时发生,那么我们判断这种情况是否发生只需

【BZOJ】2301: [HAOI2011]Problem b(莫比乌斯+分块)

http://www.lydsy.com/JudgeOnline/problem.php?id=2301 和这题不是差不多的嘛--[BZOJ]1101: [POI2007]Zap(莫比乌斯+分块) 唯一不同的地方是这题有下界.. 下界除以k的时候取上界,然后分块的时候因为有4个数,所以要分成4块来搞.. 然后就行了.. #include <cstdio> #include <cstring> #include <cmath> #include <string>

【BZOJ】1146: [CTSC2008]网络管理Network(树链剖分+线段树套平衡树+二分 / dfs序+树状数组+主席树)

第一种做法(时间太感人): 这题我真的逗了,调了一下午,疯狂造数据,始终找不到错. 后来发现自己sb了,更新那里没有打id,直接套上u了.我.... 调了一下午啊!一下午的时光啊!本来说好中午A掉去学习第二种做法,噗 好吧,现在第一种做法是hld+seg+bst+二分,常数巨大,log^4级别,目前只会这种. 树剖后仍然用线段树维护dfs序区间,然后在每个区间建一颗平衡树,我用treap,(这题找最大啊,,,囧,并且要注意,这里的rank是比他大的数量,so,我们在二分时判断要判断一个范围,即要

最大权闭合图 &amp;&amp; 【BZOJ】1497: [NOI2006]最大获利

最大权闭合图详细请看胡伯涛论文<最小割模型在信息学竞赛中的应用>,我在这里截图它的定义以及一些东西. 假设我们有一个图,点集的出边都是连到点集的,那么称这个为闭合图.现在这些点集都有个权值,我们要选择某个闭合图使得权值最大. 回到此题: 最大获利这一题,我们可以这样看,用户群和中转站为带权的点集,用户群的权为收益,中转站的权为负的成本,即0-成本,用户群向其中两个中转站连弧,那么这个就是一个闭合图. 我们要求这个闭合图的权值和最大,即最大收益,那么就能转移到上面的求最大权闭合图的做法去了. 做

【BZOJ】1012: [JSOI2008]最大数maxnumber(树状数组+区间最值)

http://www.lydsy.com/JudgeOnline/problem.php?id=1012 树状数组原来我只懂得sum和add的操作,今天才知道可以有求区间最值的操作,我学习了一下写了个,1a了. 区间最值其实和区间求和差不多,就是将sum数组的含义转移到max,然后通过特定的区间更新max. 在区间求和中,当我们维护max[i]的时候,要找到它前面所有的max[j]来更新,在这里因为是树状数组,所以可以降成一个log级,画图可知,max[i]需要的max只有max[i-2^0],