返回顶部

【比赛】高一下三调

A. 李时珍的皮肤衣

看不出规律就打表
打表

	int n=100;
	for(int k=1;k<=n;k++)
	{
		memset(vis,0,sizeof(vis));
		int ans=1;
		while(!vis[k])
		{
			for(int i=1;i<=k;i++)
			{
				if(!vis[i])
				{
					vis[i]=1;
					ans++;
					break;
				}else vis[i]=0;
			}
		}	
		cout<<ans<<endl;	
	}
点击查看代码
#include <bits/stdc++.h>
#define ll __int128
using namespace std;
long long n;
void p(ll x)
{
	if(!x)return;
	p(x/10);
	cout<<int(x%10);
}
ll qpow(ll a,ll b)
{
	ll ans=1;
	while(b)
	{
		if(b&1)ans=ans*a%n;
		a=a*a%n;
		b>>=1;
	}
	return ans;
}
int main()
{
	freopen("lsz.in","r",stdin);
	freopen("lsz.out","w",stdout);	
	cin>>n;
	ll pp=(qpow(2,n-1)+1+n)%n;
	if(!pp)cout<<0;
	else p(pp);
	return 0;
}

B. 马大嘴的废话

首先如果用hash话会T

Hash
#include <bits/stdc++.h>
#define ll long long
#define ull long long
using namespace std;
const int N =1e4+5,B=233;
int n,m,len[N];ull ha[N][25],p[25];
string s,x;
void get(int d)
{
	len[d]=s.size();
	for(int i=1;i<=len[d];i++)
	{
		ha[d][i]=ha[d][i-1]*B+s[i-1];		
	}
}
ull Hash(int l,int r,int i)
{
	return ha[i][r]-ha[i][l-1]*p[r-l+1];
}
int main()
{
	ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
	freopen("mdz.in","r",stdin);
	freopen("mdz.out","w",stdout);	
	cin>>n;
	p[0]=1;
	for(int i=1;i<=20;i++)p[i]=p[i-1]*B;
	for(int i=1;i<=n;i++)
	{
		cin>>s;
		get(i);
	}
	cin>>m;
	for(int i=1;i<=m;i++)
	{
		cin>>x;
		ull has=0;
		int l=x.size();
		for(int i=1;i<=l;i++)
		{
			has=has*B+x[i-1];		
		}
		int ans=0;
		for(int j=1;j<=n;j++)
		{
			if(len[j]<l)continue;
			else 
			{
				for(int st=1;st<=len[j]-l+1;st++)
				{
					if(Hash(st,st+l-1,j)==has)
					{
						ans++;
						break;
					}
				}
			}
		}
		cout<<ans<<endl;
	}
	return 0;
}

我们可以考虑字典树,如何在树中插入呢,当输入一个字符串时,不能只插入一个整串,这样不方便查找,必须把这个字符串的子串插入,方便查找,用一个数组同步记录每个字符出现次数

然后需要用数组记录一下当前子串属于那个整串,防止记重

优化后
#include <bits/stdc++.h>
#define ll long long
#define ull long long
using namespace std;
const int N =1e4+5,B=233;
int n,m;int son[N*50][27],num[N*50][27],cnt=1;int vis[N*50][27];
string s,x;
void insert(const string &s,int id)
{
	int len=s.size()-1,now=1;
	for(int i=0;i<=len;i++)
	{
		int ch=s[i]-'a';
		if(!son[now][ch])
		{
			son[now][ch]=++cnt;
			vis[now][ch]=id;
			num[now][ch]++;
		}else
		{
			if(vis[now][ch]!=id)num[now][ch]++,vis[now][ch]=id;
		}
		
		now=son[now][ch];
	}
}
int query(const string &s)
{
	int len=s.size()-1,now=1;
	int ans=0;
	for(int i=0;i<=len;i++)
	{
		int ch=s[i]-'a';
		if(!son[now][ch])
		{
			return 0;
		}
		ans=num[now][ch];
		now=son[now][ch];
	}
	return ans;	
}
int main()
{
	ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
	freopen("mdz.in","r",stdin);
	freopen("mdz.out","w",stdout);	
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		cin>>s;
		int len=s.size()-1;
		for(int k=0;k<=len;k++)
		{
			string tmp=s.substr(k,len-k+1);
			insert(tmp,i);		
		}
	}
	cin>>m;
	for(int i=1;i<=m;i++)
	{
		cin>>x;
		cout<<query(x)<<endl;
	}
	return 0;
}
/*

*/

D. 清理牛棚

用DP的话,我们设当前状态为i,f[i]表示0~i所需的最短时间,我们需要和前面区间比较
这是我们可以用线段树优化,维护m到e之间的最小值,这样动态转移方程为

\[f[i]=min(f[i],w_i+query(1,l_i-1,r_i)) \]

还有一个注意的点,最后答案右端点比e大的都要比较,取最优值
l-1是继承上一个区间的最小值

点击查看代码
#include <bits/stdc++.h>
#define ll long long
#define lid (rt<<1)
#define rid (rt<<1|1)
using namespace std;
const int mod = 86399,N=1e4+5;
int n,m,e;
ll sum;
struct ac
{
	int st,en,s;
}a[N];
int f[mod*4];
struct tree
{
	int l,r,w;
}st[mod*5];
void pushup(int rt)
{
	st[rt].w=min(st[lid].w,st[rid].w);
}
void buildtree(int rt,int l,int r)
{
	st[rt].l=l;st[rt].r=r;
	if(l==r)
	{
		st[rt].w=f[l];
		return;
	}
	int mid=(l+r)>>1;
	buildtree(lid,l,mid);
	buildtree(rid,mid+1,r);	
	pushup(rt);
}
void modify(int rt,int l,int r,int val)
{
	if(l<=st[rt].l&&st[rt].r<=r)
	{
		st[rt].w=val;
		return;
	}
	int mid=(st[rt].l+st[rt].r)>>1;
	if(l<=mid)modify(lid,l,r,val);
	if(r>mid)modify(rid,l,r,val);
	pushup(rt);
}
int query(int rt,int l,int r)
{
	if(l<=st[rt].l&&st[rt].r<=r)
	{
		return st[rt].w;
	}
	int mid=(st[rt].l+st[rt].r)>>1;
	int ans=INT_MAX;
	if(l<=mid)ans=min(query(lid,l,r),ans);
	if(r>mid)ans=min(query(rid,l,r),ans);	
	return ans;
}
bool cmp(ac a,ac b)
{
	return a.en<b.en;	
}

int main()
{	
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
//	freopen("clean_ex.in","r",stdin);
	freopen("clean.in","r",stdin);
	freopen("clean.out","w",stdout);	
	cin>>n>>m>>e;
	memset(f,0x3f,sizeof(f));
//	for(int i=m;i<=e;i++)f[i]=INT_MAX;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i].st>>a[i].en>>a[i].s;
		sum+=a[i].s;
	}
	sort(a+1,a+1+n,cmp);	
	f[m]=0;
	
	buildtree(1,m,e);
	for(int i=1;i<=n;i++)
	{
//		int ch=a[i].en-a[i].st+1;
		f[a[i].en]=min(f[a[i].en],query(1,a[i].st-1,a[i].en)+a[i].s);
		modify(1,a[i].en,a[i].en,f[a[i].en]);
		if(a[i].en>=e)
		{
			if(f[a[i].en]>sum)cout<<-1;
			else cout<<f[a[i].en];
			return 0;
		}
//		for(int k=st;k<=i;k++)f[k]=min(f[i],f[k]);
	}

	return 0;
	
}
/*
3 0 4
0 2 3
3 4 2
0 0 1
*/

E. 历史研究

  1. 开longlong
  2. 注意细节
  3. 要离散化
    先说分块的做法,首先分块,按块预先处理处每个元素出现次数的前缀和,然后预先处理处i~j块之间的答案编号
    查询时,我们用桶记录出现次数与重要度的乘积,散块暴力,整块直接出答案(记的加上分块中的),然后比较哪个最大即可
点击查看代码
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N =1e5+5;
int n,q,sq,st[500],en[500],belong[N],tot,ans[500][500];
ll b[N],a[N],cnt[500][N];map <ll,int> mp;
void init()
{
	sq=sqrt(n);
	for(int i=1;i<=sq;i++)
	{
		st[i]=n/sq*(i-1)+1;
		en[i]=n/sq*i;
	}
	en[sq]=n;
	for(int i=1;i<=sq;i++)
	{
		for(int j=st[i];j<=en[i];j++)
		{
			belong[j]=i;
		}
	}
	for(int i=1;i<=sq;i++)
	{
		for(int j=1;j<=n;j++)cnt[i][j]=cnt[i-1][j];
		for(int j=st[i];j<=en[i];j++)
		{
			cnt[i][a[j]]++;
		}
	}
	ll res=0,id=0;
	for(int i=1;i<=sq;i++)
	{
		for(int j=i;j<=sq;j++)
		{
			ans[i][j]=ans[i][j-1];
			res=b[ans[i][j]]*(cnt[j][ans[i][j]]-cnt[i-1][ans[i][j]]);
			id=ans[i][j-1];
			for(int k=st[j];k<=en[j];k++)
			{
				int p=a[k];
				if(res<b[p]*(cnt[j][p]-cnt[i-1][p]))
				{
					res=b[p]*(cnt[j][p]-cnt[i-1][p]);
					id=p;
				}
			}
			ans[i][j]=id;
		}
	}	
}
ll tong[N];
ll query(int l,int r)
{
	ll Ans=0;
	if(belong[l]==belong[r])
	{
		for(int i=l;i<=r;i++)
		{
			tong[a[i]]+=b[a[i]];
			Ans=max(Ans,tong[a[i]]);
		}
		for(int i=l;i<=r;i++)tong[a[i]]=0;
	}else
	{
		int res=ans[belong[l]+1][belong[r]-1];
		for(int i=l;i<=en[belong[l]];i++)
		{
			if(!tong[a[i]]&&a[i]!=res)
			{
				tong[a[i]]+=b[a[i]]*(cnt[belong[r]-1][a[i]]-cnt[belong[l]][a[i]]);
			}
			tong[a[i]]+=b[a[i]];
			Ans=max(tong[a[i]],Ans);
		}	
		for(int i=st[belong[r]];i<=r;i++)
		{
			if(!tong[a[i]]&&a[i]!=res)
			{
				tong[a[i]]+=b[a[i]]*(cnt[belong[r]-1][a[i]]-cnt[belong[l]][a[i]]);
			}
			tong[a[i]]+=b[a[i]];
			Ans=max(tong[a[i]],Ans);
		}
		Ans=max(Ans,(tong[res]+(cnt[belong[r]-1][res]-cnt[belong[l]][res])*b[res]));
		for(int i=l;i<=en[belong[l]];i++)tong[a[i]]=0;
		for(int i=st[belong[r]];i<=r;i++)tong[a[i]]=0;	
		
	}
	return Ans;
}
int main()
{
	ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//	freopen("lsyj_ex.in","r",stdin);
//	freopen("a.in","r",stdin);
//	freopen("a.out","w",stdout);	
	cin>>n>>q;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i];
		if(!mp[a[i]])
		{
			mp[a[i]]=++tot;
			b[tot]=a[i];
		}
		a[i]=mp[a[i]];
	}
//	for(int i=1;i<=n;i++)
//	{
//		cout<<a[i]<<" ";
//	}
//	cout<<endl;
	int l,r;
	init();
	for(int i=1;i<=q;i++)
	{
		cin>>l>>r;
		cout<<query(l,r)<<endl;
		
	}
	return 0;
	
}
/*
5 5
9 8 7 8 9
1 2
3 4
4 4
1 4
2 4
*/

还可以用滚动莫队

点击查看代码
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N =1e5+5;
int n,q,sq,st[500],en[500],belong[N];ll tot[N];
ll b[N],a[N],ans;map <ll,ll> mp;
struct ac
{
	int l,r,id;
}qq[N];
void init()
{
	sq=sqrt(n);
	for(int i=1;i<=sq;i++)
	{
		st[i]=n/sq*(i-1)+1;
		en[i]=n/sq*i;
	}
	en[sq]=n;
	for(int i=1;i<=sq;i++)
	{
		for(int j=st[i];j<=en[i];j++)
		{
			belong[j]=i;
		}
	}
}
bool cmp(ac a,ac b)
{
	int p=belong[a.l],q=belong[b.l];
	if(p!=q)return p<q;
//	if(a.r==a.r)return a.l>b.l;
//	else 
		return a.r<b.r;
}
ll ls[N],rs[N],cols[N],cors[N];
void add(int x)
{
	rs[x]+=b[x];
	ans=max(ans,rs[x]);
}
void add2(int x)
{
	ls[x]+=b[x];
	ans=max(ans,rs[x]+ls[x]);	
}
int nn=0;
void memset(int *a,int l,int len)
{
	for(int i=0;i<=nn;i++)a[i]=0;
}
void memcpy(int *a,int *b,int len)
{
	for(int i=0;i<=nn;i++)a[i]=b[i];
}
int main()
{
	ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//	freopen("lsyj_ex.in","r",stdin);
	freopen("a.in","r",stdin);
	freopen("a.out","w",stdout);	
	cin>>n>>q;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i];
		if(!mp[a[i]])
		{
			mp[a[i]]=++nn;
			b[nn]=a[i];
		}
		a[i]=mp[a[i]];
	}
//	for(int i=1;i<=n;i++)
//	{
//		cout<<a[i]<<" ";
//	}
//	cout<<endl;
	int l,r;
	init();
	for(int i=1;i<=q;i++)
	{
		cin>>l>>r;
		qq[i]={l,r,i};
	}
	sort(qq+1,qq+1+q,cmp);
	for(int i=1;i<=q;)
	{
		int j=i;
		while(j<=q&&belong[qq[i].l]==belong[qq[j].l])j++;
		int right=en[belong[qq[i].l]];
		while(i<j&&qq[i].r<=right)
		{
			ans=0;
			memset(ls,0,sizeof(ls));
			memset(rs,0,sizeof(rs));
			int l=qq[i].l,r=qq[i].r;
			for(int k=l;k<=r;k++){add(a[k]);}
			tot[qq[i].id]=ans;
			i++;
		}
		ans=0;
		memset(ls,0,sizeof(ls));
		memset(rs,0,sizeof(rs));
		int l=right+1,r=right;
		while(i<j)
		{
			while(r<qq[i].r){r++;add(a[r]);}
			ll copy=ans;
			memcpy(cols,ls,sizeof(ls));
			memcpy(cors,rs,sizeof(rs));	
			while(l>qq[i].l){l--;add2(a[l]);}			
			tot[qq[i].id]=ans;
			l=right+1;
			ans=copy;
			memcpy(ls,cols,sizeof(cols));
			memcpy(rs,cors,sizeof(cors));	
			i++;
		}
		ans=0;
		memset(ls,0,sizeof(ls));
		memset(rs,0,sizeof(rs));
	}
	for(int i=1;i<=q;i++)
	{
		cout<<tot[i]<<endl;
	}
	return 0;
	
}
/*
5 5
9 8 7 8 9
1 2
3 4
4 4
1 4
2 4
*/

优化了一下

点击查看代码
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N =1e5+5;
int n,q,sq,st[500],en[500],belong[N];ll tot[N];
ll b[N],a[N],ans;map <ll,ll> mp;
struct ac
{
	int l,r,id;
}qq[N];
void init()
{
	sq=sqrt(n);
	for(int i=1;i<=sq;i++)
	{
		st[i]=n/sq*(i-1)+1;
		en[i]=n/sq*i;
	}
	en[sq]=n;
	for(int i=1;i<=sq;i++)
	{
		for(int j=st[i];j<=en[i];j++)
		{
			belong[j]=i;
		}
	}
}
bool cmp(ac a,ac b)
{
	int p=belong[a.l],q=belong[b.l];
	if(p!=q)return p<q;
//	if(a.r==a.r)return a.l>b.l;
//	else 
		return a.r<b.r;
}
ll rs[N],cols[N],cors[N];
void add(int x)
{
	rs[x]+=b[x];
	ans=max(ans,rs[x]);
}
void add2(int x)
{
	rs[x]+=b[x];
	ans=max(ans,rs[x]);	
}
int nn=0;
void del(int x)
{
	rs[x]-=b[x];
}
void memset(int *a,int l,int len)
{
	for(int i=0;i<=nn;i++)a[i]=0;
}
void memcpy(int *a,int *b,int len)
{
	for(int i=0;i<=nn;i++)a[i]=b[i];
}
int main()
{
	ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//	freopen("lsyj_ex.in","r",stdin);
	#ifdef ONLINE_JUDGE
	freopen("a.in","r",stdin);
	freopen("a.out","w",stdout);
	#endif	
	cin>>n>>q;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i];
		if(!mp[a[i]])
		{
			mp[a[i]]=++nn;
			b[nn]=a[i];
		}
		a[i]=mp[a[i]];
	}
//	for(int i=1;i<=n;i++)
//	{
//		cout<<a[i]<<" ";
//	}
//	cout<<endl;
	int l,r;
	init();
	for(int i=1;i<=q;i++)
	{
		cin>>l>>r;
		qq[i]={l,r,i};
	}
	sort(qq+1,qq+1+q,cmp);
	for(int i=1;i<=q;)
	{
		int j=i;
		while(j<=q&&belong[qq[i].l]==belong[qq[j].l])j++;
		int right=en[belong[qq[i].l]];
		while(i<j&&qq[i].r<=right)
		{
			ans=0;
//			memset(ls,0,sizeof(ls));
			memset(rs,0,sizeof(rs));
			int l=qq[i].l,r=qq[i].r;
			for(int k=l;k<=r;k++){add(a[k]);}
			tot[qq[i].id]=ans;
			i++;
		}
		ans=0;
//		memset(ls,0,sizeof(ls));
		memset(rs,0,sizeof(rs));
		int l=right+1,r=right;
		while(i<j)
		{
			while(r<qq[i].r){r++;add(a[r]);}
			ll copy=ans;
			while(l>qq[i].l){l--;add2(a[l]);}			
			tot[qq[i].id]=ans;
			
			while(l<=right){del(a[l]);l++;}//这样回退快多了
			ans=copy;
			l=right+1;
			i++;
		}
		ans=0;
//		memset(ls,0,sizeof(ls));
		memset(rs,0,sizeof(rs));
	}
	for(int i=1;i<=q;i++)
	{
		cout<<tot[i]<<endl;
	}
	return 0;
	
}
/*
5 5
9 8 7 8 9
1 2
3 4
4 4
1 4
2 4
*/
posted @ 2024-05-03 16:36  wlesq  阅读(24)  评论(0编辑  收藏  举报