【比赛】高一下三调
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. 历史研究
- 开longlong
- 注意细节
- 要离散化
先说分块的做法,首先分块,按块预先处理处每个元素出现次数的前缀和,然后预先处理处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
*/