慢慢张开你的眼睛|

两只风小鱼

园龄:2年10个月粉丝:3关注:3

8.17总结

自动刷题机

solution
二分答案找最大最小值
考试时二分写错了

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;
}

生日聚会

solution
是一道dp,考场上完全没有看出来,唉~

设计状态为:h[i][j][s][d]表示已经选了i个男生,j个女生,且在任意序列中,男生减女生的差最大为k,女生减男生的差最大为h的方案数;

状态转移方程为:f[i+1][j][s+1][max(d1,0)]+=f[i][j][s][d]
//新加入为男生

f[i][j+1][max(s1,0)][d+1]+=f[i][j][s][d]
//新加入为女生

目标状态为:i=0kj=0kf[n][m][i][j]

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;
}

随机序列

solution
找规律后,线段树维护
规律3n12suma1+3n22suma2++302suman1+suman,其中sumai=j=1iaj;

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;
}

供给侧改革

solution
因为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;
}
posted @   两只风小鱼  阅读(11)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起