JZOJ4866【NOIP2016提高A组集训第8场11.5】禅与园林艺术

55 篇文章 0 订阅
32 篇文章 0 订阅

Description

上了大学之后,小W和小Z一起报了一门水课,在做作业时遇到了问题。有一个长度为 n 的数列{ai},为一列树木的美观值。现在有m 次询问,每次给出三个数l,r和P,询问对于所有的l <= l’ <= r’ <= r (a[l’] + a[l’ + 1] + … + a[r’]) mod P的最小值。

Data Constraint

对于20%的数据
1 <= n, m <= 1000,1 <= l <= r <= n, 1 <= P <= 100,0 <= a[i] <= 10^9
对于另外的30%的数据
1 <= n, m <= 50000,1 <= l <= r <= n, 1 <= P <= 10,0 <= a[i] <= 10^9
对于100%的数据
1 <= n, m <= 50000, 1 <= l <= r <= n, 1 <= P <= 100, 0 <= a[i] <= 10^9

Solution

我们设1~i的前缀和为s[i],那么对于一个点l’,r’,他们的答案显然是(s[r’]-s[l’])%P。假设我们固定l’,假设两个r1’,r’的(s[r’]-s[l’])%P相同,那么显然(s[r1’]-s[r’])%P=0。所以我们可以断定,除非(s[r’]-s[l’])%P两两不相同,否则答案一定为零。那么,现在对于一个询问l,r,假设他们之间的距离大于P,那么显然一定会出现(s[r’]-s[l’])%P相同的情况,所以我们直接输出答案0即可,否则暴力跑一下就好了

Code

#include<iostream>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define ll long long
using namespace std;
const int mo=100,maxn=50005;
struct code{
    int a,l,r,b;
}b[maxn];
int n,m,i,t,j,k,l,num,p,r,mi,x,y,yy;
ll s[maxn],a[maxn],ans[maxn];
bool bz[mo];
bool cmp(code x,code y){
    return x.a<y.a || x.a==y.a && x.r<y.r;
}
int main(){
    freopen("garden.in","r",stdin);freopen("garden.out","w",stdout);
//  freopen("data.in","r",stdin);
    scanf("%d%d",&n,&m);
    for (i=1;i<=n;i++)
        scanf("%d",&a[i]);
    for (i=1;i<=m;i++)
        scanf("%d%d%d",&b[i].l,&b[i].r,&b[i].a),b[i].b=i;
    sort(b+1,b+m+1,cmp);
    for (i=1;i<=m;i++){
        p=b[i].a;l=b[i].l;r=b[i].r;
        mi=1e9;bz[0]=true;
        if (r-l+1<=p){
            for (j=l;j<=r;j++){
                t=0;
                for (k=j;k<=r;k++){
                    t=(t+a[k])%p;
                    mi=min(mi,t);
                }
            }
            ans[b[i].b]=mi;
        }
    }
    for (i=1;i<=m;i++)
        printf("%d\n",ans[i]);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值