1537: [POI2005]Aut- The Bus

Time Limit: 5 Sec  Memory Limit: 64 MB
Submit: 158  Solved: 100
[Submit][Status]

Description

Byte
City 的街道形成了一个标准的棋盘网络 – 他们要么是北南走向要么就是西东走向. 北南走向的路口从 1 到 n编号, 西东走向的路从1 到
m编号. 每个路口用两个数(i, j) 表示(1 <= i <= n, 1 <= j <= m).
Byte City里有一条公交线, 在某一些路口设置了公交站点. 公交车从 (1, 1) 发车, 在(n, m)结束.公交车只能往北或往东走.
现在有一些乘客在某些站点等车. 公交车司机希望在路线中能接到尽量多的乘客.帮他想想怎么才能接到最多的乘客.

Input

第一行三个数n, m 和 k –
表示北南走向的路的个数以及西东走向的路和乘客等车的站点的个数. ( 1 <= n <= 10^9, 1 <= m <=
10^9, 1 <= k <= 10^5).
接下来k 行每行描述一个公交站的信息.第 i + 1 行三个正整数 xi, yi 和 pi, 1 <= xi <= n, 1
<= yi <= m, 1 <= pi <= 10^6. 表示在(xi, yi) 有 pi 个乘客在等车.
每个路口在数据中最多出现一次,乘客总数不会超过1 000 000 000.

Output

一个数表示最多能接到的乘客数量.

Sample Input

8 7 11
4 3 4
6 2 4
2 3 2
5 6 1
2 5 2
1 5 5
2 1 1
3 1 1
7 7 1
7 4 2
8 6 2

Sample Output

11

HINT

Source

[Subm

题解:

先离散化,然后按x坐标排序,数组维护每一行的最大值,然后用线段树把这些最大值串起来,支持单点修改和区间查询最大值操作,然后就可以DP了。

1A了比较爽。

代码:线段树

 #include<cstdio>

 #include<cstdlib>

 #include<cmath>

 #include<cstring>

 #include<algorithm>

 #include<iostream>

 #include<vector>

 #include<map>

 #include<set>

 #include<queue>

 #include<string>

 #define inf 1000000000

 #define maxn 100100

 #define maxm 500+100

 #define eps 1e-10

 #define ll long long

 #define pa pair<int,int>

 #define for0(i,n) for(int i=0;i<=(n);i++)

 #define for1(i,n) for(int i=1;i<=(n);i++)

 #define for2(i,x,y) for(int i=(x);i<=(y);i++)

 #define for3(i,x,y) for(int i=(x);i>=(y);i--)

 #define mod 1000000007

 using namespace std;

 inline int read()

 {

     int x=,f=;char ch=getchar();

     while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}

     while(ch>=''&&ch<=''){x=*x+ch-'';ch=getchar();}

     return x*f;

 }
struct rec{int x,id;}b[maxn];
struct recc{int x,y,w;}a[maxn];
struct seg{int l,r,mx;}t[*maxn];
int n,m,k,tot,mx[maxn],f[maxn];
inline bool cmp(rec a,rec b)
{
return a.x<b.x;
}
inline bool cmp2(recc a,recc b)
{
return a.x<b.x||(a.x==b.x&&a.y<b.y);
}
void build(int k,int l,int r)
{
t[k].l=l;t[k].r=r;
if(l==r)return;
int mid=(l+r)>>;
build(k<<,l,mid);build(k<<|,mid+,r);
}
inline void pushup(int k)
{
t[k].mx=max(t[k<<].mx,t[k<<|].mx);
}
void change(int k,int x,int y)
{
int l=t[k].l,r=t[k].r,mid=(l+r)>>;
if(l==r){t[k].mx=y;return;}
if(x<=mid)change(k<<,x,y);else change(k<<|,x,y);
pushup(k);
}
int query(int k,int x,int y)
{
int l=t[k].l,r=t[k].r,mid=(l+r)>>;
if(l==x&&r==y)return t[k].mx;
if(y<=mid)return query(k<<,x,y);
else if(x>mid)return query(k<<|,x,y);
else return max(query(k<<,x,mid),query(k<<|,mid+,y));
} int main() { freopen("input.txt","r",stdin); freopen("output.txt","w",stdout); n=read();m=read();k=read();
for1(i,k)a[i].x=read(),a[i].y=read(),a[i].w=read();
a[++k].x=n;a[k].y=m;
for1(i,k)b[i].x=a[i].x,b[i].id=i;
sort(b+,b+k+,cmp);
for1(i,k)
{
if(i==||b[i].x!=b[i-].x)tot++;
a[b[i].id].x=tot;
}
for1(i,k)b[i].x=a[i].y,b[i].id=i;
sort(b+,b+k+,cmp);
tot=;
for1(i,k)
{
if(i==||b[i].x!=b[i-].x)tot++;
a[b[i].id].y=tot;
}
sort(a+,a+k+,cmp2);
build(,,k);
for1(i,k)
{
//cout<<query(1,1,a[i].y)<<endl;
f[i]=query(,,a[i].y)+a[i].w;
if(f[i]>mx[a[i].y]){mx[a[i].y]=f[i];change(,a[i].y,f[i]);}
//cout<<i<<' '<<a[i].x<<' '<<a[i].y<<' '<<a[i].w<<' '<<f[i]<<endl;
}
printf("%d\n",f[k]); return ; }

看了题解发现做法类似,但是树状数组居然可以维护最大值!!!

仔细想了想之后发现,树状数组实际上是不能维护区间最大值,因为树状数组需要满足区间减法,而最大值不满足这样。

但是树状数组可以维护前缀最大值!!!

而本题就是查询前缀最大值。

orzzz

代码:树状数组

 #include<cstdio>

 #include<cstdlib>

 #include<cmath>

 #include<cstring>

 #include<algorithm>

 #include<iostream>

 #include<vector>

 #include<map>

 #include<set>

 #include<queue>

 #include<string>

 #define inf 1000000000

 #define maxn 100100

 #define maxm 500+100

 #define eps 1e-10

 #define ll long long

 #define pa pair<int,int>

 #define for0(i,n) for(int i=0;i<=(n);i++)

 #define for1(i,n) for(int i=1;i<=(n);i++)

 #define for2(i,x,y) for(int i=(x);i<=(y);i++)

 #define for3(i,x,y) for(int i=(x);i>=(y);i--)

 #define mod 1000000007

 using namespace std;

 inline int read()

 {

     int x=,f=;char ch=getchar();

     while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}

     while(ch>=''&&ch<=''){x=*x+ch-'';ch=getchar();}

     return x*f;

 }
struct rec{int x,id;}b[maxn];
struct recc{int x,y,w;}a[maxn];
int n,m,k,tot,ans,mx[maxn],s[maxn],f[maxn];
inline bool cmp(rec a,rec b)
{
return a.x<b.x;
}
inline bool cmp2(recc a,recc b)
{
return a.x<b.x||(a.x==b.x&&a.y<b.y);
}
inline void change(int x,int y)
{
for(;x<=tot;x+=x&(-x))s[x]=max(s[x],y);
}
inline int ask(int x)
{
int tt=;
for(;x;x-=x&(-x))tt=max(tt,s[x]);
return tt;
} int main() { freopen("input.txt","r",stdin); freopen("output.txt","w",stdout); n=read();m=read();k=read();
for1(i,k)a[i].x=read(),a[i].y=read(),a[i].w=read();
a[++k].x=n;a[k].y=m;
for1(i,k)b[i].x=a[i].x,b[i].id=i;
sort(b+,b+k+,cmp);
for1(i,k)
{
if(i==||b[i].x!=b[i-].x)tot++;
a[b[i].id].x=tot;
}
for1(i,k)b[i].x=a[i].y,b[i].id=i;
sort(b+,b+k+,cmp);
tot=;
for1(i,k)
{
if(i==||b[i].x!=b[i-].x)tot++;
a[b[i].id].y=tot;
}
sort(a+,a+k+,cmp2);
for1(i,k)
{
//cout<<ask(a[i].y)<<endl;
int tmp=ask(a[i].y)+a[i].w;
if(tmp>mx[a[i].y]){mx[a[i].y]=tmp;change(a[i].y,tmp);}
//cout<<i<<' '<<a[i].x<<' '<<a[i].y<<' '<<a[i].w<<' '<<f[i]<<endl;
ans=max(ans,tmp);
}
printf("%d\n",ans); return ; }

靠树状数组刷到了rank423333

BZOJ1537: [POI2005]Aut- The Bus的更多相关文章

  1. 「BZOJ1537」Aut – The Bus(变形Dp+线段树/树状数组 最优值维护)

    网格图给予我的第一反应就是一个状态 f[i][j] 表示走到第 (i,j) 这个位置的最大价值. 由于只能往下或往右走转移就变得显然了: f[i][j]=max{f[i-1][j], f[i][j-1 ...

  2. bzoj千题计划148:bzoj1537: [POI2005]Aut- The Bus

    http://www.lydsy.com/JudgeOnline/problem.php?id=1537 朴素的转移:dp[i][j]=max(dp[i][j-1],dp[i-1][j])+p[i][ ...

  3. bzoj 1537: [POI2005]Aut- The Bus 线段树

    bzoj 1537: [POI2005]Aut- The Bus 先把坐标离散化 设f[i][j]表示从(1,1)走到(i,j)的最优解 这样直接dp::: f[i][j] = max{f[i-1][ ...

  4. BZOJ 1537: [POI2005]Aut- The Bus(dp + BIT)

    对y坐标离散化, 然后按x坐标排序, dp. 一个点(x, y), 设到达这个点接到的最多乘客数为t, 那么t可以用来更新y'>=y的所有点.用树状数组维护最大值. -------------- ...

  5. 树状数组 二维偏序【洛谷P3431】 [POI2005]AUT-The Bus

    P3431 [POI2005]AUT-The Bus Byte City 的街道形成了一个标准的棋盘网络 – 他们要么是北南走向要么就是西东走向. 北南走向的路口从 1 到 n编号, 西东走向的路从1 ...

  6. 洛谷P3431 [POI2005]AUT-The Bus

    P3431 [POI2005]AUT-The Bus 题目描述 The streets of Byte City form a regular, chessboardlike network - th ...

  7. Bzoj 1537: [POI2005]Aut- The Bus 题解 [由暴力到正解]

    1537: [POI2005]Aut- The Bus Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 387  Solved: 264[Submit][S ...

  8. 洛谷 P3431:[POI2005]AUT-The Bus(离散化+DP+树状数组)

    题目描述 The streets of Byte City form a regular, chessboardlike network - they are either north-south o ...

  9. bzoj 1537 [POI2005]Aut- The Bus(DP+BIT)

    [题意] 顺序经过k个点,求获得的最大权值和. [思路] 设f[i]表示到第i个点,则有转移式: f[i]=min{ f[j]+w[i] } x[j]<=x[i],y[j]<=y[i] 满 ...

随机推荐

  1. java设计模式演示样例

    创建模式 1.工厂方法模式(Factory Method)  将程序中创建对象的操作,单独出来处理,创建一个产品的工厂接口,把实际的工作转移到详细的子类.大大提高了系统扩展的柔性,接口的抽象化处理给相 ...

  2. PHP安全编程:shell命令注入(转)

    使用系统命令是一项危险的操作,尤其在你试图使用远程数据来构造要执行的命令时更是如此.如果使用了被污染数据,命令注入漏洞就产生了. exec()是用于执行shell命令的函数.它返回执行并返回命令输出的 ...

  3. [转] Java中ArrayList类的用法

    1.什么是ArrayList ArrayList就是传说中的动态数组,用MSDN中的说法,就是Array的复杂版本,它提供了如下一些好处: 动态的增加和减少元素 实现了ICollection和ILis ...

  4. 从 ReactiveCocoa 中能学到什么?不用此库也能学以致用

    从知道ReactiveCocoa开始就发现对这个库有不同的声音,上次参加<T>技术沙龙时唐巧对在项目中已全面使用FRP的代码家提出为什么这种编程模型出现了这么长时间怎么像ReactiveC ...

  5. Android之发送短信的两种方式

    SMS涉及的主要类SmsManager 实现SMS主要用到SmsManager类,该类继承自java.lang.Object类,下面我们介绍一下该类的主要成员. 公有方法: ArrayList< ...

  6. [Android]如何创建一个View的分割线

    如何创建一个View的分割线,如上图 我们见介绍三种可以创建看起来很不错的view的分割线,如在button之间添加分割线. 这个例子是将为LinearLayout内的三个Button间添加分割线. ...

  7. discuz, 使用同一数据库, 只是换个环境, 数据就不一样了

    如题, 本以为是由于某些冲突导致, 细查之后, 发现是开了缓存了, 把缓存关掉或是在后台清理缓存就OK了 后台清理缓存, 全局--性能优化--内存优化  清理缓存 关闭缓存, 修改全局配置文件, co ...

  8. jsp中的c标签

    核心标签库 引用: <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> ...

  9. Android设计图(标注、切图)

    1.Android: 1)Android的单位是dp 2)分为ldpi/mdpi/hdpi/xhdpi/xxhdpi. 3)分辨率对应DPI ldpi  QVGA (240×320) mdpi  HV ...

  10. sql - 复制表

    1,复制表结构和内容 1)这个表: select * into new_table_name from old_table_name ref:SQL复制数据表及表结构