树状数组优化dp——nkoj3771公共汽车

探讨了在特定公交线路上如何最大化接载乘客数量的问题。通过算法优化,实现从起点到终点路径上的乘客数量最大化。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

P3771公共汽车
时间限制 : - MS   空间限制 : 65536 KB 
评测说明 : 1000ms
问题描述

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

输入格式

第一行三个数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.

输出格式

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

样例输入

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

样例输出

11


来源  POI2005
















#include<cstdio> 
#include<iostream> 
#include<algorithm> 
#include<cstdlib> 
#include<cstring> 
#include<map> 
using namespace std; 
inline void _read(int &x){ 
    char t=getchar();bool sign=true; 
    while(t<'0'||t>'9') 
    {if(t=='-')sign=false;t=getchar();} 
    for(x=0;t>='0'&&t<='9';t=getchar())x=x*10+t-'0'; 
    if(!sign)x=-x; 
} 
const int maxn=500005; 
int totx,toty; 
map<int,int> mapx; 
map<int,int> mapy; 
int x_appear[maxn],y_appear[maxn];
int n,m,k; 
struct node{ 
    int x,y,w; 
    node(){} 
    node(int a,int b,int c){x=a;y=b;w=c;} 
}; 
node stop[maxn]; 
int c[maxn]; 
int f[maxn];
int lowbit(int x){return x&(-x);} 
void modify(int x,int d){ 
    int i,j,k; 
    for(i=x;i<=maxn;i+=lowbit(i)){
        c[i]=max(c[i],d); 
    } 
} 
int getmax(int x){
	int ans=0,i,j;
	for(i=x;i;i-=lowbit(i)){
		ans=max(ans,c[i]);
	}
	return ans;
} 
bool cmp(node a,node b){
	if(a.x==b.x)return a.y<b.y;
	else return a.x<b.x;
}
int main(){ 
	int i,j,ans=0;
	cin>>n>>m>>k;
	for(i=1;i<=k;i++){
		int x,y;
		_read(stop[i].x);_read(stop[i].y);_read(stop[i].w);
		x=stop[i].x;
		y=stop[i].y;
		if(mapx[x]==0)x_appear[++totx]=x;
		if(mapy[y]==0)y_appear[++toty]=y;
	}
	sort(x_appear+1,x_appear+1+totx);
	sort(y_appear+1,y_appear+1+toty);
	for(i=1;i<=totx;i++){
		mapx[x_appear[i]]=i;
	}
	for(i=1;i<=toty;i++){
		mapy[y_appear[i]]=i;
	}
	sort(stop+1,stop+1+k,cmp);
	for(i=1;i<=k;i++){
		int temp=getmax(mapy[stop[i].y]);
		f[i]=temp+stop[i].w;
		modify(mapy[stop[i].y],f[i]);
		ans=max(ans,f[i]);
	}
	cout<<ans;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值