8.17总结
自动刷题机
二分答案找最大最小值
考试时二分写错了
AC Code
#include<bits/stdc++.h>
using namespace std;
#define ll long long
inline ll read()
{
ll x=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9')
{
if(ch=='-')f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9')
{
x=x*10+ch-'0';
ch=getchar();
}
return x*f;
}
const int N=1e5+5;
ll n,k,a[N];
ll check(ll x)
{
int cnt=0;
ll sum=0;
for(int i=1;i<=n;++i){
sum=max(0ll,sum+a[i]);
if(sum>=x){
++cnt;
sum=0;
}
}
return cnt;
}
ll ans1=-1,ans2=-1;
void get_max()
{
ll l=1,r=1e18;
while(l<=r){
ll mid=(l+r)>>1;
if(check(mid)>=k){
if(check(mid)==k)ans2=mid;
l=mid+1;
}
else if(check(mid)<k)
r=mid-1;
}
return ;
}
void get_min()
{
ll l=1,r=1e14;
while(l<=r){
ll mid=(l+r)>>1;
if(check(mid)>k)
l=mid+1;
else if(check(mid)<=k){
r=mid-1;
if(check(mid)==k)ans1=mid;
}
}
return ;
}
int main()
{
// freopen("autoac.in","r",stdin);
// freopen("autoac.out","w",stdout);
n=read(),k=read();
for(int i=1;i<=n;i++)
{
a[i]=read();
}
get_min();
get_max();
if(ans1==-1)printf("-1\n");
else printf("%lld %lld\n",ans1,ans2);
return 0;
}
生日聚会
是一道dp,考场上完全没有看出来,唉~
设计状态为:表示已经选了i个男生,j个女生,且在任意序列中,男生减女生的差最大为k,女生减男生的差最大为h的方案数;
状态转移方程为:
//新加入为男生
//新加入为女生
目标状态为:
AC Code
#include<bits/stdc++.h>
using namespace std;
inline int read()
{
int x=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9')
{
if(ch=='-')f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9')
{
x=x*10+ch-'0';
ch=getchar();
}
return x*f;
}
int n,m,k;
const int mod=12345678;
int f[155][155][25][25];
int main()
{
n=read(),m=read(),k=read();
f[0][0][0][0]=1;
for(int i=0;i<=n;i++)
{
for(int j=0;j<=m;j++)
{
for(int s=0;s<=k;s++)
{
for(int d=0;d<=k;d++)
{
(f[i+1][j][s+1][max(d-1,0)]+=f[i][j][s][d])%=mod;
(f[i][j+1][max(s-1,0)][d+1]+=f[i][j][s][d])%=mod;
}
}
}
}
int ans=0;
for(int i=0;i<=k;i++)
{
for(int j=0;j<=k;j++)
{
ans=(ans+f[n][m][i][j])%mod;
}
}
cout<<ans<<endl;
return 0;
}
随机序列
找规律后,线段树维护
规律,其中;
AC Code
#include<bits/stdc++.h>
using namespace std;
#define ll long long
inline ll read()
{
ll x=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9')
{
if(ch=='-')f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9')
{
x=x*10+ch-'0';
ch=getchar();
}
return x*f;
}
const int mod=1e9+7;
const int N=1e5+5;
ll n,q,a[N];
ll dat[N];
//ll sum[N],dat[N],ans[N];
ll qow(ll x,ll y)
{
ll res=1;
while(y>0)
{
if(y&1)
{
res*=x;res%=mod;
}
x*=x;x%=mod;y>>=1;
}
return res%mod;
}
struct ww{
int l,r;
ll sum,tag=1;
}tr[N<<3];
void updat(int p)
{
tr[p].sum=(tr[p<<1].sum%mod+tr[p<<1|1].sum%mod)%mod;
}
void build(int p,int l,int r)
{
tr[p].l=l,tr[p].r=r;
if(l==r)
{
tr[p].sum=dat[l]%mod;
return ;
}
int mid=(l+r)>>1;
build(p<<1,l,mid);
build(p<<1|1,mid+1,r);
updat(p);
}
void pushdown(int p)
{
if(tr[p].tag!=1)
{
tr[p<<1].sum=(tr[p<<1].sum*tr[p].tag)%mod;
tr[p<<1|1].sum=(tr[p<<1|1].sum*tr[p].tag)%mod;
tr[p<<1].tag=(tr[p<<1].tag*tr[p].tag)%mod;
tr[p<<1|1].tag=(tr[p<<1|1].tag*tr[p].tag)%mod;
tr[p].tag=1;
}
}
void change(int p,int l1,int r1,ll x)
{
int l=tr[p].l,r=tr[p].r;
if(r<l1||r1<l)return ;
if(l1<=l&&r<=r1)
{
pushdown(p);
tr[p].tag=(tr[p].tag*x)%mod;
tr[p].sum=(tr[p].sum*tr[p].tag)%mod;
return ;
}
pushdown(p);
int mid=(l+r)>>1;
if(l1<=mid)change(p<<1,l1,r1,x);
if(r1>mid)change(p<<1|1,l1,r1,x);
updat(p);
}
int main()
{
n=read(),q=read();
dat[n]=1;ll k=1;
for(int i=n-1;i>=1;i--)
{
dat[i]=k*2%mod;
k*=3;k%=mod;
}
// sum[0]=1;
ll sum1=1;
for(int i=1;i<=n;i++)
{
a[i]=read();
sum1=sum1*a[i]%mod;
dat[i]=sum1*dat[i]%mod;
// sum[i]=sum[i-1]*a[i]%mod;
// ans[i]=(dat[i]*sum[i]%mod+ans[i-1])%mod;
}
build(1,1,n);
ll x,y;
for(int i=1;i<=q;i++)
{
x=read(),y=read();
ll tmp=qow(a[x],mod-2)%mod*y%mod;
change(1,x,n,tmp);
a[x]=y;
printf("%lld\n",tr[1].sum%mod);
// ll tmp=qow(a[x],mod-2);
// for(int j=x;j<=n;j++)
// {
// sum[j]=sum[j]*tmp%mod*y%mod;
// ans[j]=(dat[j]*sum[j]%mod+ans[j-1])%mod;
// }
// a[x]=y;
// printf("%lld\n",ans[n]);
}
return 0;
}
供给侧改革
因为01序列是随机的,所以后缀的最长公共前缀和不超过40,所以我们只需要暴力记录所有后缀的前40位,并用id数组记录与当前后缀所列举的前缀相同的最近的后缀序号,f数组记录以i为开始的后缀,与它长度为j的前缀相同最近的后缀的开头
然后对于每个(l,r)的询问,暴力枚举长度j,然后l跳到f[r][j]+1上,累计答案ans
AC Code
#include<bits/stdc++.h>
using namespace std;
inline int read()
{
int x=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9')
{
if(ch=='-')f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9')
{
x=x*10+ch-'0';
ch=getchar();
}
return x*f;
}
const int N=1e5+5;
int n,q,cnt;
int a[N],son[N*50][2];
int f[N][50],id[N*50];
void insert(int x)
{
int p=0;
for(int i=x;i<=x+40;i++)
{
if(i>n)return ;
if(!son[p][a[i]])
son[p][a[i]]=++cnt;
p=son[p][a[i]];
f[x][i-x+1]=id[p];
id[p]=x;
}
}
void init()
{
for(int i=1;i<=n;i++)insert(i);
for(int i=2;i<=n;i++)
{
for(int j=1;j<=40;j++)
{
f[i][j]=max(f[i][j],f[i-1][j]);
if(!f[i-1][j])break;
}
}
}
int data(int l,int r)
{
int ans=0;
for(int i=40;i&&l<=r;i--)
{
if(f[r][i]>=l)
{
ans+=(f[r][i]-l+1)*i;
l=f[r][i]+1;
}
}
return ans;
}
int main()
{
n=read(),q=read();
char s;
for(int i=1;i<=n;i++)
{
cin>>s;
a[i]=s-'0';
}
init();
int l,r;
for(int i=1;i<=q;i++)
{
l=read(),r=read();
cout<<data(l,r)<<endl;
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步