题解 P1956 【Sum_NOI导刊2009提高(5)】
数据水炸的一道题
以至于我拿一个卡时的暴力过掉了还拿了rk1???
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int s[200000],a[200000],ans=1e9+7,kkk=0,n,k,p;
int getin()
{
int x=0;char ch=getchar();
while(ch<'0'||ch>'9')ch=getchar();
while(ch>='0'&&ch<='9')x=x*10+ch-48,ch=getchar();
return x;
}
int rem(int a,int b)
{
a-=b;
if(a<0)a+=p;
return a;
}
int main()
{
n=getin(),k=getin(),p=getin();
for(int i=1;i<=n;i++)a[i]=getin()%p,s[i]=(s[i-1]+a[i])%p;
for(int i=0;i<n&&kkk<=4500000;i++)
for(int j=i+1;j<=n;j++)
{
int d=rem(s[j],s[i]);
if(d>=k&&d<ans)ans=d;
kkk++;
}
cout<<ans<<endl;
}
最终版本的卡时肯定有大爷能卡进100ms
还是来说(可能的不过我觉得补星)正解
首先前缀和一下顺便取模
然后可以发现我们要求的就是
因为要不小于k,所以减去一个k变成
假设已知
这个东西看起来就是一个前驱的样子了
所以可以二叉查找树解决
为什么不用平衡树?
因为不好写随机数据显然二叉查找树的复杂度可以保证不然暴力怎么能过
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int ch[200000][2],f[200000],rt,id,w[200000]={1e9+7},m,opt,x,ans=1e9+7,s[200000],n,k,p;
int prep(int x)
{
int lst=0,o=rt;
while(o)
{
if(x>w[o])lst=o,o=ch[o][1];
else o=ch[o][0];
}
return w[lst];
}
void ins(int x)
{
if(!rt){w[++id]=x,rt=id;return;}
int o=rt,lst;
while(o)
{
lst=o;
if(x>w[o])o=ch[o][1];
else if(x<w[o])o=ch[o][0];
else break;
}
if(!o)
{
w[o=++id]=x;
f[id]=lst,ch[lst][x>w[lst]]=id;
}
}
int getin()
{
int x=0,f=1;char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')f=-1,ch=getchar();
while(ch>='0'&&ch<='9')x=x*10+ch-48,ch=getchar();
return x*f;
}
int main()
{
n=getin(),k=getin(),p=getin();
for(int i=1;i<=n;i++)s[i]=(s[i-1]+getin())%p;
ins(s[1]+k);
for(int i=2;i<=n;i++)
{
ans=min(ans,(s[i]-min(prep(s[i]+1),prep(s[i]+p+1))+k+p)%p);
ins(s[i]+k);
}
cout<<ans<<endl;
}