zoukankan      html  css  js  c++  java
  • [POI2011]LIZ-Lollipop(前缀和)

    原题

    题面

    Solution

    我是不会告诉你我一开始写了一个二分答案+rand的算法的。。。
    这样子你可以获得80分的好成绩!!!

    #pragma GCC diagnostic error "-std=c++11"
    #pragma GCC optimize(2)
    #pragma GCC optimize(3)
    #pragma GCC optimize("Ofast")
    #pragma GCC optimize("inline")
    #pragma GCC optimize("-fgcse")
    #pragma GCC optimize("-fgcse-lm")
    #pragma GCC optimize("-fipa-sra")
    #pragma GCC optimize("-ftree-pre")
    #pragma GCC optimize("-ftree-vrp")
    #pragma GCC optimize("-fpeephole2")
    #pragma GCC optimize("-ffast-math")
    #pragma GCC optimize("-fsched-spec")
    #pragma GCC optimize("unroll-loops")
    #pragma GCC optimize("-falign-jumps")
    #pragma GCC optimize("-falign-loops")
    #pragma GCC optimize("-falign-labels")
    #pragma GCC optimize("-fdevirtualize")
    #pragma GCC optimize("-fcaller-saves")
    #pragma GCC optimize("-fcrossjumping")
    #pragma GCC optimize("-fthread-jumps")
    #pragma GCC optimize("-funroll-loops")
    #pragma GCC optimize("-fwhole-program")
    #pragma GCC optimize("-freorder-blocks")
    #pragma GCC optimize("-fschedule-insns")
    #pragma GCC optimize("inline-functions")
    #pragma GCC optimize("-ftree-tail-merge")
    #pragma GCC optimize("-fschedule-insns2")
    #pragma GCC optimize("-fstrict-aliasing")
    #pragma GCC optimize("-fstrict-overflow")
    #pragma GCC optimize("-falign-functions")
    #pragma GCC optimize("-fcse-skip-blocks")
    #pragma GCC optimize("-fcse-follow-jumps")
    #pragma GCC optimize("-fsched-interblock")
    #pragma GCC optimize("-fpartial-inlining")
    #pragma GCC optimize("no-stack-protector")
    #pragma GCC optimize("-freorder-functions")
    #pragma GCC optimize("-findirect-inlining")
    #pragma GCC optimize("-fhoist-adjacent-loads")
    #pragma GCC optimize("-frerun-cse-after-loop")
    #pragma GCC optimize("inline-small-functions")
    #pragma GCC optimize("-finline-small-functions")
    #pragma GCC optimize("-ftree-switch-conversion")
    #pragma GCC optimize("-foptimize-sibling-calls")
    #pragma GCC optimize("-fexpensive-optimizations")
    #pragma GCC optimize("-funsafe-loop-optimizations")
    #pragma GCC optimize("inline-functions-called-once")
    #pragma GCC optimize("-fdelete-null-pointer-checks")
    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #include<math.h>
    #include<algorithm>
    #include<iostream>
    #include<queue>
    #define ll long long
    #define file(a) freopen(a".in","r",stdin)//;freopen(a".out","w",stdout)
    using namespace std;
    inline int gi(){
        int sum=0,f=1;char ch=getchar();
        while(ch>'9' || ch<'0'){if(ch=='-')f=-f;ch=getchar();}
        while(ch>='0' && ch<='9'){sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();}
        return f*sum;
    }
    inline ll gl(){
        ll sum=0,f=1;char ch=getchar();
        while(ch>'9' || ch<'0'){if(ch=='-')f=-f;ch=getchar();}
        while(ch>='0' && ch<='9'){sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();}
        return f*sum;
    }
    int a[2000010],sum[2000010];
    struct node{
        int id,val;
        bool operator<(const node b)const{
            return val<b.val;
        }
    }d[2000010];
    int main(){
        srand(time(NULL));
    #ifndef ONLINE_JUDGE
        file("example");
    #endif
        int i,j,n,m,k;
        n=gi();m=gi();
        for(i=1;i<=n;i++){
            char ch=getchar();
            a[i]=ch=='W'?1:2;
        }
        for(i=1;i<=n;i++)sum[i]=sum[i-1]+a[i];
        for(i=1;i<=n;i++){
            d[i]=(node){i,rand()};
        }
        sort(d+1,d+n+1);
        while(m--){
            k=gi();int flag=0;
            for(int x=1;x<=n;x++){
                i=d[x].id;
                int l=i,r=n,ans=0;
                while(l<=r){
                    int mid=(l+r)>>1;
                    if(sum[mid]-sum[i-1]>k)r=mid-1;
                    else if(sum[mid]-sum[i-1]<k)l=mid+1;
                    else{ans=mid;break;}
                }
                if(ans){
                    printf("%d %d
    ",i,ans);flag=1;
                    break;
                }
            }
            if(!flag)puts("NIE");
        }
        return 0;
    }
    

    这是一道比较有思维难度的题目,我们考虑一下如果一段区间有1,那么显然都可以完成对吧。
    这里给一个比较简单的证明:
    (Sum)表示前i个数的和,(sum_i)表示i往后有多少个T.我们考虑当前这个数如果是T(2),那么有如下两种情况

    • i向后延续的长度>1向后延续的长度,则有:
      (Sum-1=a_{sum_1+2}+a_{sum_1+3}+...+a_{sum_1+i})

    这个可以这么想,我们把它差分一下,变成:
    (a_1+a_2+...+a_{sum_1+i}-a_1-a_2-...-a_{sum_1+1})
    因为(1~sum_1)都是2,所以前面的数都是2.
    然后我们考虑第一个式子(a_1+a_2+a_3+...+a_{sum_1+i})
    因为i向后延续的长度>1向后延续的长度,所以我们考虑把这i个数往前移,然后把1往后延续的长度放到后面,就有
    原式=(a_1+a_2+...+a_{sum_1+i}-a_1-a_2-a_{sum_1+1}=Sum-1)


    • 如果i延续的长度不能够到n,则有:
      (Sum-1=a_{sum_i+1}+a_{sum_i+2}+...+a_{sum_i+i})

    同理可证


    那么就可以写出下面这段代码了.

    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #include<math.h>
    #include<algorithm>
    #include<iostream>
    #include<queue>
    #define ll long long
    #define file(a) freopen(a".in","r",stdin)//;freopen(a".out","w",stdout)
    using namespace std;
    inline int gi(){
        int sum=0,f=1;char ch=getchar();
        while(ch>'9' || ch<'0'){if(ch=='-')f=-f;ch=getchar();}
        while(ch>='0' && ch<='9'){sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();}
        return f*sum;
    }
    inline ll gl(){
        ll sum=0,f=1;char ch=getchar();
        while(ch>'9' || ch<'0'){if(ch=='-')f=-f;ch=getchar();}
        while(ch>='0' && ch<='9'){sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();}
        return f*sum;
    }
    int a[2000010],sum[2000010],Sum,l[2000010],r[2000010];
    int main(){
    #ifndef ONLINE_JUDGE
        file("example");
    #endif
        int i,j,n,m,k;
        n=gi();m=gi();
        for(i=1;i<=n;i++){
            char ch=getchar();
            if(ch=='T')a[i]=2;
            else a[i]=1;
        }
        for(i=n;i;i--)sum[i]=a[i]==2?(sum[i+1]+1):0;
        int Sum=0;
        for(i=1;i<=n;i++){
            Sum+=a[i];
            l[Sum]=1;r[Sum]=i;
            if(a[i]==2)
                if(sum[i]>sum[1])l[Sum-1]=sum[1]+2,r[Sum-1]=sum[1]+i;
                else if(sum[i]!=n-i+1)l[Sum-1]=sum[i]+1,r[Sum-1]=sum[i]+i;
        }
        while(m--){
            k=gi();
            if(l[k])printf("%d %d
    ",l[k],r[k]);
            else puts("NIE");
        }
        return 0;
    }
    
  • 相关阅读:
    在C#代码中应用Log4Net(二)典型的使用方式
    在C#代码中应用Log4Net(一)简单使用Log4Net
    Windows Azure Active Directory (2) Windows Azure AD基础
    Windows Azure Virtual Network (6) 设置Azure Virtual Machine固定公网IP (Virtual IP Address, VIP) (1)
    Windows Azure Active Directory (1) 前言
    Azure China (6) SAP 应用在华登陆 Windows Azure 公有云
    Microsoft Azure News(3) Azure新的基本实例上线 (Basic Virtual Machine)
    Microsoft Azure News(2) 在Microsoft Azure上运行SAP应用程序
    Microsoft Azure News(1) 新的数据中心Japan East, Japan West and Brazil South
    Windows Azure HandBook (2) Azure China提供的服务
  • 原文地址:https://www.cnblogs.com/cjgjh/p/9807642.html
Copyright © 2011-2022 走看看