zoukankan      html  css  js  c++  java
  • 【BZOJ】【1986】【USACO 2004 Dec】/【POJ】【2373】划区灌溉

    DP/单调队列优化


      首先不考虑奶牛的喜欢区间,dp方程当然是比较显然的:$ f[i]=min(f[k])+1,i-2*b leq k leq i-2*a $  当然这里的$i$和$k$都是偶数啦~这个应该很好理解吧……每次喷灌的都是一个偶数长度的区间嘛……

      那么加上奶牛的喜欢区间的话,只需这样:当$ i>cow[j].x $时,令$ i=cow[j].y , j++$ 也就是说中间的位置全部不考虑放喷灌器。

      显然我们对于每个节点的 k 是可以用单调队列维护的!嗯看到这里的同学可以先自己试着去写写看啦~

      如果过了样例不要着急,来试试我这组数据:

    2 16
    2 4
    7 8
    6 12

    Trick:

      每个奶牛的喜欢区间是一个【开区间】!分界点是可以被不同的喷灌器灌溉的(仔细看看样例的图)

      一开始英文题面嘛……看了中文没细看英文……没看到还有【不合法情况输出-1】so sad……

      每个f[i]不能刚算出来就弹队尾+进队尾,因为此时下一个位置为 i+2 ,可能会把能够转移到i+2的合法状态弹出去,而f[i]是不能转移到f[i+2]的!(因为有a的限制)所以会造成f[i+2]计算错误(当然f[l]就也有可能出错了。

      事实上由于我们维护的队列是一个合法状态区间,所以目前不合法的状态不应该进队,而是应该在每次更新f[i]之前让 f[i-2*a] 进队,这样可以保证队列中所有节点都为合法状态。

      然而!!刚才那种做法会有漏洞!因为我们会在遇到奶牛的喜欢区间的时候跳!过!去!所以一些合法状态就会来不及进队(比如我给的数据中的f[6]……所以在遇到奶牛区间的时候要将这个区间内所有合法的状态进队(当然要维护队列单调性了……需要弹队尾)

     1 /**************************************************************
     2     Problem: 1986
     3     User: Tunix
     4     Language: C++
     5     Result: Accepted
     6     Time:40 ms
     7     Memory:9092 kb
     8 ****************************************************************/
     9  
    10 //POJ 2373
    11 #include<cmath>
    12 #include<vector>
    13 #include<cstdio>
    14 #include<cstring>
    15 #include<cstdlib>
    16 #include<iostream>
    17 #include<algorithm>
    18 #define rep(i,n) for(int i=0;i<n;++i)
    19 #define F(i,j,n) for(int i=j;i<=n;++i)
    20 #define D(i,j,n) for(int i=j;i>=n;--i)
    21 #define pb push_back
    22 using namespace std;
    23 int getint(){
    24     int v=0,sign=1; char ch=getchar();
    25     while(ch<'0'||ch>'9'){ if (ch=='-') sign=-1; ch=getchar();}
    26     while(ch>='0'&&ch<='9'){ v=v*10+ch-'0'; ch=getchar();}
    27     return v*=sign;
    28 }
    29 const int N=1e6+10,INF=~0u>>2;
    30 typedef long long LL;
    31 /******************tamplate*********************/
    32 //#define debug
    33 struct Cow{
    34     int x,y;
    35     Cow(){}
    36     bool operator < (const Cow &b)const{
    37         return x<b.x || (x==b.x && y<b.y);
    38     }
    39 }cow[1010];
    40 int f[N],n,l,a,b;
    41 int q[N];
    42 int main(){
    43 #ifndef ONLINE_JUDGE
    44     freopen("2373.in","r",stdin);
    45 //  freopen("2373.out","w",stdout);
    46 #endif
    47     n=getint(); l=getint(); a=getint(); b=getint();
    48     F(i,1,n) cow[i].x=getint(),cow[i].y=getint();
    49     sort(cow+1,cow+n+1);
    50 #ifdef debug
    51     F(i,1,n) printf("%d %d
    ",cow[i].x,cow[i].y);
    52     cout <<endl;
    53 #endif
    54     int j=1;
    55     F(i,1,l) f[i]=INF;
    56     int st=0,ed=0;
    57     f[0]=0;
    58     q[ed++]=0;
    59     for(int i=2;i<=l;i+=2){
    60         while(i>cow[j].x && j<=n){
    61             int last=i;
    62             i=max(i,(cow[j].y+1)/2*2),j++;
    63             for(int I=last;I<=i;I+=2)
    64                 if (f[I-2*a]!=INF){
    65                     while(st<ed && f[q[ed-1]]>f[I-2*a]) ed--;
    66                     q[ed++]=I-2*a;
    67                 }
    68         }
    69         while(st<ed && q[st]<i-2*b) st++;
    70         if(f[i-2*a]!=INF){
    71             while(st<ed && f[q[ed-1]]>f[i-2*a]) ed--;
    72             q[ed++]=i-2*a;
    73         }
    74         if (st<ed && i-q[st]>=2*a) f[i]=f[q[st]]+1;
    75     }
    76 #ifdef debug
    77     F(i,1,l) printf("%d ",f[i]==INF ? -1 : f[i]);
    78     cout <<endl;
    79 #endif
    80     printf("%d
    ",f[l]==INF ? -1 : f[l]);
    81     return 0;
    82 }
    View Code
  • 相关阅读:
    为什么要使用MQ消息中间件?
    趣图:这是招聘超神级别的程序员?
    基于redis的分布式锁的分析与实践
    我的java问题排查工具单
    趣图:看到这些窗户,我想插上几根网线
    SpringBoot+MyBatis+MySQL读写分离(实例)
    IntelliJ IDEA 常用快捷键
    ex3 多分类和神经网络
    9、神经网络的学习
    神经网络--反向传播详细推导过程
  • 原文地址:https://www.cnblogs.com/Tunix/p/4324172.html
Copyright © 2011-2022 走看看