zoukankan      html  css  js  c++  java
  • 2019 ICPC Asia Nanchang Regional E Eating Plan 离散化+前缀和

    题意:

    给你n个盘子,这n个盘子里面分别装着1!到n!重量的食物,对于每一个询问k,找出一个最短的区间,使得区间和 mod 998857459 大于或等于k

    盘子数量 n<=1e5 询问次数 m<=1e4

    题解:

    坑点在于此题模数998857459=4*773*2803 是个合数,因此任何a>=2803 a!=0

    因此,只需考虑非0的盘子作为端点,暴力枚举$(max(n,2802))^2$个区间。

    我使用的方式是记录阶乘取模非0节点的值和位置,然后求前缀和

    再枚举左右端点,记录区间和取模和区间长度

    再将区间按照区间和从小到大排序

    再把值从小到大的区间从后往前,维护取得大于等于该值所需区间长度的最小值。

    询问时在排好序的区间数组上lower_bound,返回该点记录的最小区间长度.

    #include<iostream>
    #include<algorithm>
    #include<vector>
    #define MOD 998857459
    #define INF 0x3f3f3f3f
    using namespace std;
    long long poww[3000];
    long long res[100005];
    //long long a[100005];
    struct Array{
        long long val;
        long long index;
        long long sum;
    }a[3000];
    long long asiz=0;
    struct Ans{
        long long sum;
        long long len;
        long long minlen;
        
        friend bool operator < (const Ans &a,const Ans &b){
            return a.sum<b.sum;
        }
        friend bool operator > (const Ans &a,const Ans &b){
            return a.sum>b.sum;
        }
    }ans[9000000];
    long long anssiz=0;
    //vector<Ans> ans;
    int main(){
        poww[1]=1;
        for(long long i=2;i<=2805;i++){
            poww[i]=1LL*poww[i-1]*i%MOD;
            //printf("%lld
    ",poww[i]);
        }
        
        long long n,m;
        scanf("%lld %lld",&n,&m);
        
        for(long long i=1;i<=n;i++){
            long long t;
            scanf("%lld",&t);
            if(t<=2805){
                asiz++;
                a[asiz].index=i;
                a[asiz].val=poww[t];
            }
        }
        
        //a[1].sum=a[1].val;
        for(long long i=1;i<=asiz;i++){
            a[i].sum=a[i-1].sum+a[i].val;
        }
        
        
        //memset(res,INF,sizeof res);
        for(long long i=1;i<=asiz;i++){
            for(long long j=i;j<=asiz;j++){
                //ans.push_back(aa);
                anssiz++;
                ans[anssiz].len=a[j].index-a[i].index+1;
                ans[anssiz].sum=(a[j].sum-a[i-1].sum)%MOD;
                //res[j-i+1]=max(res[j-i+1],a[j].sum-a[i-1].sum);
            }
        }
        
        sort(ans+1,ans+1+anssiz);
        
        ans[anssiz].minlen=ans[anssiz].len;
        
        for(long long i=anssiz-1;i>=1;i--){
            ans[i].minlen=min(ans[i+1].minlen,ans[i].len);
            //printf("*%lld %lld
    ",ans[i].sum,ans[i].minlen);
        }
        //for(int i=1;i<=anssiz;i++){
            //printf("*%lld %lld %lld
    ",ans[i].sum,ans[i].len,ans[i].minlen);
        //}
        for(long long i=1;i<=m;i++){
            long long k;
            scanf("%lld",&k);
            Ans tmp;
            tmp.sum=k;
            long long aa=lower_bound(ans+1,ans+1+anssiz,tmp)-ans;
            //printf("%lld
    ",aa);
            if(aa==anssiz+1)printf("-1
    ");
            else printf("%lld
    ",ans[aa].minlen);
        }
        return 0;
    }
  • 相关阅读:
    win 10安装 wamp 丢失msvcr110.dll 解决办法
    技巧——快读快写
    考前一些复习东东
    2019.11月4日模拟赛(早)
    2019 年 10 月训练赛(10.30早)
    2019 年 10 月训练赛(10.30晚)
    NOIP 鸡王争霸赛
    2019 10.3模拟
    CSP考纲及高精度计算
    CCF 全国信息学奥林匹克联赛复赛模拟
  • 原文地址:https://www.cnblogs.com/isakovsky/p/12034606.html
Copyright © 2011-2022 走看看