BZOJ1537: [POI2005]Aut- The Bus
1537: [POI2005]Aut- The Bus
Time Limit: 5 Sec Memory Limit: 64 MB
Submit: 158 Solved: 100
[Submit][Status]
Description
City 的街道形成了一个标准的棋盘网络 – 他们要么是北南走向要么就是西东走向. 北南走向的路口从 1 到 n编号, 西东走向的路从1 到
m编号. 每个路口用两个数(i, j) 表示(1 <= i <= n, 1 <= j <= m).
Byte City里有一条公交线, 在某一些路口设置了公交站点. 公交车从 (1, 1) 发车, 在(n, m)结束.公交车只能往北或往东走.
现在有一些乘客在某些站点等车. 公交车司机希望在路线中能接到尽量多的乘客.帮他想想怎么才能接到最多的乘客.
Input
表示北南走向的路的个数以及西东走向的路和乘客等车的站点的个数. ( 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
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
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的更多相关文章
- 「BZOJ1537」Aut – The Bus(变形Dp+线段树/树状数组 最优值维护)
网格图给予我的第一反应就是一个状态 f[i][j] 表示走到第 (i,j) 这个位置的最大价值. 由于只能往下或往右走转移就变得显然了: f[i][j]=max{f[i-1][j], f[i][j-1 ...
- 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][ ...
- 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][ ...
- BZOJ 1537: [POI2005]Aut- The Bus(dp + BIT)
对y坐标离散化, 然后按x坐标排序, dp. 一个点(x, y), 设到达这个点接到的最多乘客数为t, 那么t可以用来更新y'>=y的所有点.用树状数组维护最大值. -------------- ...
- 树状数组 二维偏序【洛谷P3431】 [POI2005]AUT-The Bus
P3431 [POI2005]AUT-The Bus Byte City 的街道形成了一个标准的棋盘网络 – 他们要么是北南走向要么就是西东走向. 北南走向的路口从 1 到 n编号, 西东走向的路从1 ...
- 洛谷P3431 [POI2005]AUT-The Bus
P3431 [POI2005]AUT-The Bus 题目描述 The streets of Byte City form a regular, chessboardlike network - th ...
- Bzoj 1537: [POI2005]Aut- The Bus 题解 [由暴力到正解]
1537: [POI2005]Aut- The Bus Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 387 Solved: 264[Submit][S ...
- 洛谷 P3431:[POI2005]AUT-The Bus(离散化+DP+树状数组)
题目描述 The streets of Byte City form a regular, chessboardlike network - they are either north-south o ...
- 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] 满 ...
随机推荐
- C++高精度运算类bign (重载操作符)
大数据操作,有例如以下问题: 计算:456789135612326542132123+14875231656511323132 456789135612326542132123*14875231656 ...
- 一起学android之怎样获取手机程序列表以及程序相关信息并启动指定程序 (26)
效果图: 程序列表: watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaGFpX3FpbmdfeHVfa29uZw==/font/5a6L5L2T/fonts ...
- PHP 計算字符串長度函數
PHP內置的字符串長度函數strlen無法正確處理中文字符串,它得到的只是字符串所占的字節數.對於GB2312的中文編碼,strlen得到的值是漢字個數的2倍,而對於UTF-8編碼的中文,就是3倍的差 ...
- android studio c++ 自动补全
这两天弄起来了Android ndk,可这东西的配置实在是个问题.对于Eclipse可以通过makefile进行编译,也比较成熟.但是对Android studio来说就蛋疼了,官方是想通过gradl ...
- [转] Form表单中method="post/get'的区别
Form提供了两种数据传输的方式——get和post.虽然它们都是数据的提交方式,但是在实际传输时确有很大的不同,并且可能会对数据产生严重的影响.虽然为了方便的得到变量值,Web容器已经屏蔽了二者的一 ...
- linux服务器上的php代码通过nginx发布,解决pathinfo模式问题
附件1为修改前的正常访问php配置文件 附件2为修改后的能通过url地址访问php项目的配置文件 具体操作网址 如下:www.itokit.com/2012/0308/73275.ht ...
- Hibernate分页
1. HQL分页: Session session = HibernateUtil.getInstance().getSession(); Query query = session.createQu ...
- vsftp配置主动模式和被动模式
配置文件:/etc/vsftpd/vsftpd.conf 主动模式配置方法: 主动式连接使用的数据通道 connect_from_port_20=YES 支持数据流的被动式连接模式 pasv_enab ...
- ajax提交富文本,内容被截断,解决方法及思路
问题描述: 使用百度的UEditor富文本插件用于前端富文本编辑,后端使用jsp,提交普通文本没有问题,后来发现在提交某些指定文本时,数据查回的数据出现不完整现象:第一件事就是想到“垃圾编辑器”
- 原生js方法document.getElementsByClassName在ie8及其以下的兼容性问题
document.getElementsByClassName在ie8及其以下浏览器的兼容性问题,在ie8及其以下浏览器中不能使用,针对这个问题,下面给出详细的解决方法,感兴趣的朋友可以参考下 ...