• NOI2009 诗人小G


    Sol

    决策单调性+二分

    传说中的四边形不等式...其实做了这道题还是不会...

    证明简直吃屎//// 贴个传送门这里有部分分做法还有决策单调性的证明 byvoid

    ISA tell me that these problem could make a list to find DanDiaoXing.

    (由于...导致我可以放个表上来...)

    打表程序

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    using namespace std;
    
    #define debug(a) cout<<#a<<"="<<a<<" "
    const int N = 105;
    typedef long long LL;
    
    LL T,n,l,p;
    LL sum[N],f[N],g[N];
    
    LL pow(LL x){
    	if(x<0) x=-x;LL res=1;
    	for(int i=1;i<=p;i++) res=res*x;
    	return res;
    }
    LL F(int i,int j){ return f[j]+pow(sum[i]-sum[j]+i-j-1-l); }
    int main(){
    	freopen("in.in","r",stdin);
    	freopen("out.out","w",stdout);
    	for(cin>>T;T--;){
    		cin>>n>>l>>p;
    		for(int i=1;i<=n;i++) sum[i]=sum[i-1]+2;
    		memset(f,0x7f,sizeof(f));f[0]=0;
    		for(int i=1;i<=n;i++) for(int j=0;j<i;j++) if(f[i]>F(i,j)) g[i]=j,f[i]=F(i,j);
    		debug(n),debug(l),debug(p);cout<<endl<<"f[i]"<<endl;
    		for(int i=1;i<=n;i++) cout<<f[i]<<" ";cout<<endl;
    		cout<<"/////////////////////"<<endl;
    		cout<<endl<<"g[i]"<<endl;
    		for(int i=1;i<=n;i++) cout<<g[i]<<" ";
    //		cout<<"/////////////////////"<<endl;
    		cout<<endl<<"**************************************************"<<endl;
    	}
    	return 0;
    }
    

    输入文件

    10
    10 3 1
    10 3 2
    10 3 3
    10 3 4
    10 3 5
    10 3 6
    10 3 7
    10 3 8
    10 3 9
    10 3 10
    

    输出文件

    n=10 l=3 p=1 
    f[i]
    1 2 3 4 5 6 7 8 9 10 
    /////////////////////
    
    g[i]
    0 0 1 2 3 4 5 6 7 8 
    **************************************************
    n=10 l=3 p=2 
    f[i]
    1 2 3 4 5 6 7 8 9 10 
    /////////////////////
    
    g[i]
    0 1 2 3 4 5 6 7 8 9 
    **************************************************
    n=10 l=3 p=3 
    f[i]
    1 2 3 4 5 6 7 8 9 10 
    /////////////////////
    
    g[i]
    0 1 2 3 4 5 6 7 8 9 
    **************************************************
    n=10 l=3 p=4 
    f[i]
    1 2 3 4 5 6 7 8 9 10 
    /////////////////////
    
    g[i]
    0 1 2 3 4 5 6 7 8 9 
    **************************************************
    n=10 l=3 p=5 
    f[i]
    1 2 3 4 5 6 7 8 9 10 
    /////////////////////
    
    g[i]
    0 1 2 3 4 5 6 7 8 9 
    **************************************************
    n=10 l=3 p=6 
    f[i]
    1 2 3 4 5 6 7 8 9 10 
    /////////////////////
    
    g[i]
    0 1 2 3 4 5 6 7 8 9 
    **************************************************
    n=10 l=3 p=7 
    f[i]
    1 2 3 4 5 6 7 8 9 10 
    /////////////////////
    
    g[i]
    0 1 2 3 4 5 6 7 8 9 
    

    我们可以发现每个点的最优决策点g[i]是单调递增的...

    但是我一开始天真的认为点i的能作为最优决策点的起始位置也是单调递增的,显然他是一个凹或凸函数,并不具有单调性,意思就是我们需要维护一个双端队列用来作为最优决策点的转移.

    每次入队都需要对于队尾元素进行出队操作,就是判断该点作为最优决策点的起始位置是否比队尾元素最优决策点的起始位置更靠左,如果是,就进行出队操作.

    然后二分一下,它作为最优决策的位置.

    PS:long long存不下,double也存不下,需要long double,亲测.

    Code

    #include<cstdio>
    #include<utility>
    #include<cstring>
    #include<iostream>
    using namespace std;
     
    #define mpr(a,b) make_pair(a,b)
    const int N = 100005;
    const double lim = 1e18;
    typedef long long LL;
     
    int n,l,p,h,t;
    LL sum[N];
    int len[N],q[N],L[N],R[N];
    long double f[N];
     
    inline int in(int x=0,char ch=getchar()){ while(ch>'9'||ch<'0') ch=getchar();
        while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();return x; }
    long double MyPow(long double x){
        long double a=1;if(x<0) x=-x;
        for(int i=1;i<=p;i++) a=a*x;
        return a;
    }
    long double F(int i,int j){ return f[j]+MyPow(sum[i]-sum[j]+i-j-1-l); }
    int main(){
    //  freopen("in.in","r",stdin);
        for(int T=in();T--;puts("--------------------")){
            n=in(),l=in(),p=in();
            char tmp[50];
            for(int i=1;i<=n;i++){
                scanf("%s",tmp);
                len[i]=strlen(tmp);
                sum[i]=sum[i-1]+len[i];
            }
            h=t=1,q[t]=0;L[h]=1,R[h]=n;
            for(int i=1;i<=n;i++){
                while(R[h]<i) h++;
                f[i]=F(i,q[h]);
                while(L[t]>i&&F(L[t],q[t])>F(L[t],i)) R[t-1]=R[t],t--;
                int ll=L[t],rr=R[t],mm;
                while(ll<=rr){
                    mm=(ll+rr)>>1;
                    if(F(mm,q[t])<=F(mm,i)) ll=mm+1;
                    else rr=mm-1;
                }if(ll<=R[t]){ L[++t]=ll,R[t]=R[t-1],R[t-1]=ll-1,q[t]=i; }
            }
            if(f[n]>lim) puts("Too hard to arrange");
            else printf("%lld
    ",(long long)f[n]);
        }
        return 0;
    }
    

      

  • 相关阅读:
    xss框架(一)之浏览器通信
    Joomla未授权创建特权用户漏洞和getshell脚本解析
    从零开始写网站登录爆破(一)
    CSRF学习整理
    vue中vue2-google-maps使用谷歌地图的基础操作
    vue中百度地图API的调用
    60秒定时减少
    git操作指令,以及常规git代码操作
    taro taroUi的H5打包后路径/修改为./
    vue enter事件无效,加入native
  • 原文地址:https://www.cnblogs.com/beiyuoi/p/5806580.html
Copyright © 2020-2023  润新知