zoukankan      html  css  js  c++  java
  • poj1065 Wooden Sticks[LIS or 贪心]

    地址戳这。N根木棍待处理,每根有个长x宽y,处理第一根花费1代价,之后当处理到的后一根比前一根长或者宽要大时都要重新花费1代价,否则不花费。求最小花费代价。多组数据,N<=5000


    本来是奔着贪心来做的。首先按照套路想到排序,长优先宽再次从小到大。由于要不浪费,尽量按照顺序去找,第一次把花费仅为1的最长子序列抽出来,标记之后,再循环找下一个未被标记的最长子序列保证只花费1,这样应该是最优的。但是鉴于$N$的范围和多组数据没敢这样做,虽然后来发现数据水这样也可以过。然后瞎想到把数对$(x,y)$抽象成点,就在坐标系中用尽量少的y值单调不减的折线去覆盖上所有点。而x值天然有一个从小到大的顺序,那不就二维偏序么,再说直白一点,就是x看成下标,y看成值,找不下降子序列的最少个数的说。这个求min不下降子序列根据Dilworth定理可知,它求的就是个最长下降子序列长度,这个只能当结论记因为我也不会证233。所以就可以上$O(nlogn)$算法啦,就不怕他多组数据了。x值相同的注意一点就行,按y从小到大dp(想一想为什么)。

    维护这个这次用了树状数组因为之前没在这上面用过,发现真好写又好用啊。以y值为树状数组下标,每次找比i的a[i]小的就在0~a[i]-1这个树状数组区间内找最大值即可,最大值维护也很简单,和sum差不多(不过BIT只可以维护从1到i的,若维护区间的可能要麻烦一点),看code,或者自己画个BIT模拟一下就发现是可以维护的。

    BIT维护MAXMIN的之前没写过,其实常数蛮小的,希望以后记得使用

    Upd:有关dilworth定理的详细举例:

    • 最少不上升子序列的划分数=最长上升子序列长度
    • 最少上升子序列的划分数=最长不上升子序列长度
    • 最少不下降子序列的划分数=最长下降子序列长度
    • 最少下降子序列的划分数=最长不下降子序列长度

    也就是怎么用都行。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<cmath>
     5 #include<algorithm>
     6 #define dbg(x) cerr<<#x<<" = "<<x<<endl
     7 #define ddbg(x,y) cerr<<#x<<" = "<<x<<"   "<<#y<<" = "<<y<<endl
     8 #define lowbit(x) x&(-x)
     9 using namespace std;
    10 typedef pair<int,int> pii;
    11 typedef long long ll;
    12 template<typename T>inline char MIN(T&A,T B){return A>B?A=B,1:0;}
    13 template<typename T>inline char MAX(T&A,T B){return A<B?A=B,1:0;}
    14 template<typename T>inline T _min(T A,T B){return A<B?A:B;}
    15 template<typename T>inline T _max(T A,T B){return A>B?A:B;}
    16 template<typename T>inline T read(T&x){
    17     x=0;int f=0;char c;while(!isdigit(c=getchar()))if(c=='-')f=1;
    18     while(isdigit(c))x=x*10+(c&15),c=getchar();return f?x=-x:x;
    19 }
    20 const int N=5000+3;
    21 pii a[N];
    22 int C[N<<1];
    23 int T,n,y,f,ans;
    24 inline int Query(int x){int ret=0;for(;x;x-=lowbit(x))MAX(ret,C[x]);return ret;}
    25 inline void Add(int x,int val){for(;x<=y;x+=lowbit(x))MAX(C[x],val);}
    26 
    27 int main(){//freopen("test.in","r",stdin);freopen("test.out","w",stdout);
    28     read(T);while(T--){
    29         read(n);for(register int i=1;i<=n;++i)read(a[i].first),MAX(y,read(a[i].second));
    30         sort(a+1,a+n+1);memset(C,0,sizeof C);
    31         for(register int i=n;i;--i)MAX(ans,f=Query(a[i].second-1)+1),Add(a[i].second,f);
    32         printf("%d
    ",ans);ans=y=0;
    33     }
    34     return 0;
    35 }
  • 相关阅读:
    巧用boost库实现字符串映射消息处理函数
    Apache Continuum 1.3.6 GA 发布下载
    NetBeans 时事通讯(刊号 # 98 Apr 08, 2010)
    source insight
    vim 树形目录插件NERDTree安装及简单用法 心灵净土 博客频道 CSDN.NET
    Janus: Vim Distribution
    vim中的复制与粘贴 | WangYan BLog
    ctagsrevised
    vi的复制粘贴命令_简简单单_百度空间
    贴个自个用的vimrc zmlovelx(帅得不敢出门 c/c++群31843264) 博客频道 CSDN.NET
  • 原文地址:https://www.cnblogs.com/saigyouji-yuyuko/p/10532947.html
Copyright © 2011-2022 走看看