1. 程式人生 > 其它 >Luogu3431 [POI2005]AUT-The Bus

Luogu3431 [POI2005]AUT-The Bus

技術標籤:動態規劃資料結構# 線段樹

原題連結:https://www.luogu.com.cn/problem/P3431

AUT-The Bus

題目描述

The streets of Byte City form a regular, chessboardlike network - they are either north-south or west-east directed. We shall call them NS- and WE-streets. Furthermore, each street crosses the whole city. Every NS-street intersects every WE- one and vice versa. The NS-streets are numbered from 1 1

1 to n n n, starting from the westernmost. The WE-streets are numbered from 1 1 1 to m m m, beginning with the southernmost. Each intersection of the ii’th NS-street with the jj’th WE-street is denoted by a pair of numbers ( i , j ) (i,j) (i,j) (for 1 ≤ i ≤ n 1\le i\le n 1in, 1 ≤ j ≤ m 1\le j\le m
1jm
).

There is a bus line in Byte City, with intersections serving as bus stops. The bus begins its itinerary by the ( 1 , 1 ) (1,1) (1,1) intersection, and finishes by the ( n , m ) (n,m) (n,m) intersection. Moreover, the bus may only travel in the eastern and/or northern direction.

There are passengers awaiting the bus by some of the intersections. The bus driver wants to choose his route in a way that allows him to take as many of them as possible. (We shall make an assumption that the interior of the bus is spacious enough to take all of the awaiting passengers, regardless of the route chosen.)TaskWrite a programme which:

reads from the standard input a description of the road network and the number of passengers waiting at each intersection,finds, how many passengers the bus can take at the most,writes the outcome to the standard output.

Byte City 的街道形成了一個標準的棋盤網路 – 他們要麼是北南走向要麼就是西東走向. 北南走向的路口從 1 到 n編號, 西東走向的路從1 到 m編號. 每個路口用兩個數(i, j) 表示(1 <= i <= n, 1 <= j <= m). Byte City裡有一條公交線, 在某一些路口設定了公交站點. 公交車從 (1, 1) 發車, 在(n, m)結束.公交車只能往北或往東走. 現在有一些乘客在某些站點等車. 公交車司機希望在路線中能接到儘量多的乘客.幫他想想怎麼才能接到最多的乘客.

輸入格式

The first line of the standard input contains three positive integers nn, mm and kk - denoting the number of NS-streets, the number of WE-streets and the number of intersections by which the passengers await the bus, respectively ( 1 ≤ n ≤ 1 0 9 (1\le n\le 10^9 (1n109, 1 ≤ m ≤ 1 0 9 1\le m\le 10^9 1m109 , 1 ≤ k ≤ 1 0 5 1\le k\le 10^5 1k105 ).

The following k k k lines describe the deployment of passengers awaiting the bus, a single line per intersection. In the ( i + 1 ) (i+1) (i+1)'st line there are three positive integers x i x_i xi , y i y_i yi and p i p_i pi , separated by single spaces, 1 ≤ x i ≤ n 1\le x_i\le n 1xin, 1 ≤ y i ≤ m 1\le y_i\le m 1yim, 1 ≤ p i ≤ 1 0 6 1\le p_i\le 10^6 1pi106 . A triplet of this form signifies that by the intersection ( x i , y i ) p i (x_i,y_i)p_i (xi,yi)pi passengers await the bus. Each intersection is described in the input data once at the most. The total number of passengers waiting for the bus does not exceed 1 000 000 000 1\ 000\ 000\ 000 1000000000.

輸出格式

Your programme should write to the standard output one line containing a single integer - the greatest number of passengers the bus can take.

輸入輸出樣例

輸入 #1
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
輸出 #1
11

題解

比較簡單的一道題,因為車只能朝北或者朝西開,那麼我們就從每個點東側和南側的點轉移就好了,如果資料範圍是 1 0 3 10^3 103,直接開二維陣列迴圈即可。這道題範圍比較大,就需要離散化東西走向的座標,同時用線段樹維護區間最大值。從南到北遍歷所有的站點時,取當前位置的值和東側所有位置的最大值比較進行轉移。

程式碼

因為線段樹空間忘開 4 4 4倍痛失一A。

#include<bits/stdc++.h>
#define ls v<<1
#define rs v<<1|1
using namespace std;
const int M=1e5+5;
struct Point{int x,y,val;}pt[M];
struct node{int le,ri,mx;}tree[M<<1];
bool cmp(Point a,Point b){return a.y==b.y?a.x<b.x:a.y<b.y;}
int n,m,k,x[M];
void up(int v){tree[v].mx=max(tree[ls].mx,tree[rs].mx);}
void build(int v,int le,int ri)
{
    tree[v].le=x[le],tree[v].ri=x[ri];
    if(le==ri)return;
    int mid=le+ri>>1;
    build(ls,le,mid),build(rs,mid+1,ri);
}
void modify(int v,int x,int val)
{
    if(tree[v].le==tree[v].ri){tree[v].mx=val;return;}
    if(x<=tree[ls].ri)modify(ls,x,val);
    else modify(rs,x,val);
    up(v);
}
int ask(int v,int le,int ri)
{
    if(le>ri)return 0;
    if(le<=tree[v].le&&tree[v].ri<=ri){return tree[v].mx;}
    int r=0;
    if(le<=tree[ls].ri)r=ask(ls,le,ri);
    if(tree[rs].le<=ri)r=max(r,ask(rs,le,ri));
    return r;
}
void in()
{
    scanf("%d%d%d",&n,&m,&k);
    for(int i=1;i<=k;++i)
    {
        scanf("%d%d%d",&pt[i].x,&pt[i].y,&pt[i].val);
        x[i]=pt[i].x;
    }
}
void ac()
{
    sort(x+1,x+1+k);
    n=unique(x+1,x+1+k)-1-x;
    build(1,1,n);
    sort(pt+1,pt+1+k,cmp);
    for(int i=1;i<=k;++i)
    {
        modify(1,pt[i].x,pt[i].val+max(ask(1,pt[i].x,pt[i].x),ask(1,x[1],pt[i].x-1)));
    }
    printf("%d\n",ask(1,1,x[n]));
}
int main()
{
    in(),ac();
    system("pause");
}