zoukankan      html  css  js  c++  java
  • 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
    ",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
    ",ans);
    118 
    119     return 0;
    120 
    121 }
    View Code

    靠树状数组刷到了rank423333

  • 相关阅读:
    判断无向图G是否连通
    图的深度优先搜索与广度优先搜索
    整数变换问题
    按层次遍历二叉树
    交叉链表
    二元查找树转换成一个排序的双向链表
    简单计算器的实现
    二叉树宽度的计算
    BMP文件的读取与显示
    约瑟夫环问题
  • 原文地址:https://www.cnblogs.com/zyfzyf/p/4016500.html
Copyright © 2011-2022 走看看