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

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了比较爽。

代码:线段树

  1 #include<cstdio>
  2 
  3 #include<cstdlib>
  4 
  5 #include<cmath>
  6 
  7 #include<cstring>
  8 
  9 #include<algorithm>
 10 
 11 #include<iostream>
 12 
 13 #include<vector>
 14 
 15 #include<map>
 16 
 17 #include<set>
 18 
 19 #include<queue>
 20 
 21 #include<string>
 22 
 23 #define inf 1000000000
 24 
 25 #define maxn 100100
 26 
 27 #define maxm 500+100
 28 
 29 #define eps 1e-10
 30 
 31 #define ll long long
 32 
 33 #define pa pair<int,int>
 34 
 35 #define for0(i,n) for(int i=0;i<=(n);i++)
 36 
 37 #define for1(i,n) for(int i=1;i<=(n);i++)
 38 
 39 #define for2(i,x,y) for(int i=(x);i<=(y);i++)
 40 
 41 #define for3(i,x,y) for(int i=(x);i>=(y);i--)
 42 
 43 #define mod 1000000007
 44 
 45 using namespace std;
 46 
 47 inline int read()
 48 
 49 {
 50 
 51     int x=0,f=1;char ch=getchar();
 52 
 53     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
 54 
 55     while(ch>='0'&&ch<='9'){x=10*x+ch-'0';ch=getchar();}
 56 
 57     return x*f;
 58 
 59 }
 60 struct rec{int x,id;}b[maxn];
 61 struct recc{int x,y,w;}a[maxn];
 62 struct seg{int l,r,mx;}t[4*maxn];
 63 int n,m,k,tot,mx[maxn],f[maxn];
 64 inline bool cmp(rec a,rec b)
 65 {
 66     return a.x<b.x;
 67 }
 68 inline bool cmp2(recc a,recc b)
 69 {
 70     return a.x<b.x||(a.x==b.x&&a.y<b.y);
 71 }
 72 void build(int k,int l,int r)
 73 {
 74     t[k].l=l;t[k].r=r;
 75     if(l==r)return;
 76     int mid=(l+r)>>1;
 77     build(k<<1,l,mid);build(k<<1|1,mid+1,r);
 78 }
 79 inline void pushup(int k)
 80 {
 81     t[k].mx=max(t[k<<1].mx,t[k<<1|1].mx);
 82 }
 83 void change(int k,int x,int y)
 84 {
 85     int l=t[k].l,r=t[k].r,mid=(l+r)>>1;
 86     if(l==r){t[k].mx=y;return;}
 87     if(x<=mid)change(k<<1,x,y);else change(k<<1|1,x,y);
 88     pushup(k);
 89 }
 90 int query(int k,int x,int y)
 91 {
 92     int l=t[k].l,r=t[k].r,mid=(l+r)>>1;
 93     if(l==x&&r==y)return t[k].mx;
 94     if(y<=mid)return query(k<<1,x,y);
 95     else if(x>mid)return query(k<<1|1,x,y);
 96     else return max(query(k<<1,x,mid),query(k<<1|1,mid+1,y));
 97 }
 98 
 99 int main()
100 
101 {
102 
103     freopen("input.txt","r",stdin);
104 
105     freopen("output.txt","w",stdout);
106 
107     n=read();m=read();k=read();
108     for1(i,k)a[i].x=read(),a[i].y=read(),a[i].w=read();
109     a[++k].x=n;a[k].y=m;
110     for1(i,k)b[i].x=a[i].x,b[i].id=i;
111     sort(b+1,b+k+1,cmp);
112     for1(i,k)
113     {
114         if(i==1||b[i].x!=b[i-1].x)tot++;
115         a[b[i].id].x=tot;
116     }
117     for1(i,k)b[i].x=a[i].y,b[i].id=i;
118     sort(b+1,b+k+1,cmp);
119     tot=0;
120     for1(i,k)
121     {
122         if(i==1||b[i].x!=b[i-1].x)tot++;
123         a[b[i].id].y=tot;
124     }
125     sort(a+1,a+k+1,cmp2);
126     build(1,1,k);
127     for1(i,k)
128     {
129         //cout<<query(1,1,a[i].y)<<endl;
130         f[i]=query(1,1,a[i].y)+a[i].w;
131         if(f[i]>mx[a[i].y]){mx[a[i].y]=f[i];change(1,a[i].y,f[i]);}
132         //cout<<i<<' '<<a[i].x<<' '<<a[i].y<<' '<<a[i].w<<' '<<f[i]<<endl;
133     }
134     printf("%d\n",f[k]);
135 
136     return 0;
137 
138 }
View Code

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

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

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

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

orzzz

代码:树状数组

  1 #include<cstdio>
  2 
  3 #include<cstdlib>
  4 
  5 #include<cmath>
  6 
  7 #include<cstring>
  8 
  9 #include<algorithm>
 10 
 11 #include<iostream>
 12 
 13 #include<vector>
 14 
 15 #include<map>
 16 
 17 #include<set>
 18 
 19 #include<queue>
 20 
 21 #include<string>
 22 
 23 #define inf 1000000000
 24 
 25 #define maxn 100100
 26 
 27 #define maxm 500+100
 28 
 29 #define eps 1e-10
 30 
 31 #define ll long long
 32 
 33 #define pa pair<int,int>
 34 
 35 #define for0(i,n) for(int i=0;i<=(n);i++)
 36 
 37 #define for1(i,n) for(int i=1;i<=(n);i++)
 38 
 39 #define for2(i,x,y) for(int i=(x);i<=(y);i++)
 40 
 41 #define for3(i,x,y) for(int i=(x);i>=(y);i--)
 42 
 43 #define mod 1000000007
 44 
 45 using namespace std;
 46 
 47 inline int read()
 48 
 49 {
 50 
 51     int x=0,f=1;char ch=getchar();
 52 
 53     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
 54 
 55     while(ch>='0'&&ch<='9'){x=10*x+ch-'0';ch=getchar();}
 56 
 57     return x*f;
 58 
 59 }
 60 struct rec{int x,id;}b[maxn];
 61 struct recc{int x,y,w;}a[maxn];
 62 int n,m,k,tot,ans,mx[maxn],s[maxn],f[maxn];
 63 inline bool cmp(rec a,rec b)
 64 {
 65     return a.x<b.x;
 66 }
 67 inline bool cmp2(recc a,recc b)
 68 {
 69     return a.x<b.x||(a.x==b.x&&a.y<b.y);
 70 }
 71 inline void change(int x,int y)
 72 {
 73     for(;x<=tot;x+=x&(-x))s[x]=max(s[x],y);
 74 }
 75 inline int ask(int x)
 76 {
 77     int tt=0;
 78     for(;x;x-=x&(-x))tt=max(tt,s[x]);
 79     return tt;
 80 }
 81 
 82 int main()
 83 
 84 {
 85 
 86     freopen("input.txt","r",stdin);
 87 
 88     freopen("output.txt","w",stdout);
 89 
 90     n=read();m=read();k=read();
 91     for1(i,k)a[i].x=read(),a[i].y=read(),a[i].w=read();
 92     a[++k].x=n;a[k].y=m;
 93     for1(i,k)b[i].x=a[i].x,b[i].id=i;
 94     sort(b+1,b+k+1,cmp);
 95     for1(i,k)
 96     {
 97         if(i==1||b[i].x!=b[i-1].x)tot++;
 98         a[b[i].id].x=tot;
 99     }
100     for1(i,k)b[i].x=a[i].y,b[i].id=i;
101     sort(b+1,b+k+1,cmp);
102     tot=0;
103     for1(i,k)
104     {
105         if(i==1||b[i].x!=b[i-1].x)tot++;
106         a[b[i].id].y=tot;
107     }
108     sort(a+1,a+k+1,cmp2);
109     for1(i,k)
110     {
111         //cout<<ask(a[i].y)<<endl;
112         int tmp=ask(a[i].y)+a[i].w;
113         if(tmp>mx[a[i].y]){mx[a[i].y]=tmp;change(a[i].y,tmp);}
114         //cout<<i<<' '<<a[i].x<<' '<<a[i].y<<' '<<a[i].w<<' '<<f[i]<<endl;
115         ans=max(ans,tmp);
116     }
117     printf("%d\n",ans);
118 
119     return 0;
120 
121 }
View Code

靠树状数组刷到了rank423333

 

posted @ 2014-10-10 17:56  ZYF-ZYF  Views(330)  Comments(7Edit  收藏  举报