专项测试(数据结构1)
专项测试(数据结构1)
果然不出我所料,数据结构比后缀数组难
这个第二题的\(MLE\)完全不出我所料,考场上算着就一个\(G\)了
所以我认为卡内存也是一个非常重要的东西
推式子的能力还是不行,第一题莫比乌斯大白板,美腿出来!!!
后来呢最后一题二分还没想出来。。。。
T1 Surprise me
CF原题,我没做过
推式子,看网上题解吧
最后用一个莫比乌斯反演,不是我学的那种,是换函数那种,我学的是合适变换
然后用虚树提点,做个\(DP\)就行了
AC_code
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
int read(){
int s=0,t=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')t=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){s=(s<<3)+(s<<1)+ch-'0';ch=getchar();}
return s*t;
}
const int mod=1e9+7;
const int N=2e5+5;
int ksm(int x,int y){
int ret=1;
while(y){
if(y&1)ret=ret*x%mod;
y>>=1;x=x*x%mod;
}
return ret;
}
int n,a[N],ans,id[N];
int to[N*2],nxt[N*2],head[N],rp;
void add_edg(int x,int y){
to[++rp]=y;
nxt[rp]=head[x];
head[x]=rp;
}
int son[N],siz[N],dep[N],fa[N];
int top[N],dfn[N],dd;
void dfs_fi(int x,int f){
fa[x]=f;dep[x]=dep[f]+1;
son[x]=0;siz[x]=1;
for(int i=head[x];i;i=nxt[i]){
int y=to[i];
if(y==fa[x])continue;
//dep[y]=dep[x]+1;
dfs_fi(y,x);
siz[x]+=siz[y];
if(!son[x]||siz[y]>siz[son[x]])son[x]=y;
}
}
void dfs_se(int x,int f){
top[x]=f;dfn[x]=++dd;
if(son[x])dfs_se(son[x],f);
for(int i=head[x];i;i=nxt[i]){
int y=to[i];
if(y==son[x]||y==fa[x])continue;
dfs_se(y,y);
}
}
int LCA(int x,int y){
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]])swap(x,y);
x=fa[top[x]];
}
return dep[x]<dep[y]?x:y;
}
int p[N],pi[N],mu[N],cnt;
bool vip[N];
void xxs(){
mu[1]=1;fo(i,2,n){
if(!vip[i])p[++cnt]=i,pi[i]=i-1,mu[i]=-1;
for(int j=1;j<=cnt&&p[j]*i<=n;j++){
vip[i*p[j]]=true;
if(i%p[j]==0){
pi[i*p[j]]=pi[i]*p[j];
mu[i*p[j]]=0;
break;
}
pi[i*p[j]]=pi[i]*(p[j]-1);
mu[i*p[j]]=-mu[i];
}
}
}
int f[N],g[N],dp[N],res,tes,sum;
int w[N],num;
int sta[N],tot;
bool vis[N];
bool com(int x,int y){return dfn[x]<dfn[y];}
void vtree(){
sort(w+1,w+num+1,com);
sta[tot=1]=1;head[1]=0;rp=0;
fo(i,1,num){
if(w[i]==1)continue;
int lca=LCA(sta[tot],w[i]);
if(lca!=sta[tot]){
while(dfn[lca]<dfn[sta[tot-1]]){
add_edg(sta[tot-1],sta[tot]);
tot--;
}
if(lca!=sta[tot-1]){
head[lca]=0;
add_edg(lca,sta[tot]);
sta[tot]=lca;
}
else add_edg(lca,sta[tot]),tot--;
}
head[w[i]]=0;sta[++tot]=w[i];
}
fo(i,1,tot-1)add_edg(sta[i],sta[i+1]);
}
void DP(int x){dp[x]=0;
if(vis[x]){tes=(tes+2*pi[a[x]]*pi[a[x]]%mod*dep[x])%mod;dp[x]=pi[a[x]];}
for(int i=head[x];i;i=nxt[i]){
int y=to[i];DP(y);
tes=(tes+4*dp[x]%mod*dp[y]%mod*dep[x]%mod)%mod;
dp[x]=(dp[x]+dp[y])%mod;
}
// cout<<x<<" "<<tes<<endl;
}
signed main(){
n=read();pi[1]=1;
fo(i,1,n)a[i]=read(),id[a[i]]=i;
fo(i,1,n-1){
int x=read(),y=read();
add_edg(x,y);
add_edg(y,x);
}
dfs_fi(1,0);dfs_se(1,1);xxs();
fo(i,1,n/2){
num=res=tes=sum=0;
for(int j=i;j<=n;j+=i){
w[++num]=id[j];vis[id[j]]=true;
res=(res+2*pi[j]*dep[id[j]]%mod)%mod;
sum=(sum+pi[j])%mod;
}
vtree();dp[1]=0;DP(1);cout<<endl;
res=res*sum%mod;g[i]=(res-tes+mod)%mod;
// cout<<res<<" "<<tes<<" "<<g[i]<<endl;
for(int j=i;j<=n;j+=i)vis[id[j]]=false;
}
fo(i,1,n/2)for(int j=i;j<=n;j+=i)f[i]=(f[i]+mu[j/i]*g[j]%mod+mod)%mod;
fo(i,1,n/2)ans=(ans+f[i]*i%mod*ksm(pi[i],mod-2)%mod)%mod;
ans=ans*ksm(n*(n-1)%mod,mod-2)%mod;
printf("%lld",ans);
}
T2 神牛养成计划
两个\(trie\),一个正着,一个反着
再用个主席树判断子树交集,
考场上用了两个后缀自动机。。。。。
AC_code
#include<bits/stdc++.h>
using namespace std;
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
int read(){
int s=0,t=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')t=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){s=(s<<3)+(s<<1)+ch-'0';ch=getchar();}
return s*t;
}
const int N=2e6+5;
int rt[N];
struct ZXS{
struct POT{
int sum,ls,rs;
}tr[2000*80];
int seg;
void ins(int pr,int &x,int l,int r,int pos){
x=++seg;tr[x]=tr[pr];tr[x].sum++;
// cout<<seg<<endl;
if(l==r)return ;
int mid=l+r>>1;
if(pos<=mid)ins(tr[pr].ls,tr[x].ls,l,mid,pos);
else ins(tr[pr].rs,tr[x].rs,mid+1,r,pos);
}
int query(int pr,int x,int l,int r,int ql,int qr){
// cout<<l<<" "<<r<<" "<<ql<<" "<<qr<<" "<<tr[x].sum<<" "<<tr[pr].sum<<endl;
if(ql<=l&&r<=qr)return tr[x].sum-tr[pr].sum;
int mid=l+r>>1,ret=0;
if(ql<=mid)ret+=query(tr[pr].ls,tr[x].ls,l,mid,ql,qr);
if(qr>mid)ret+=query(tr[pr].rs,tr[x].rs,mid+1,r,ql,qr);
return ret;
}
}zxs;
struct ACM{
struct POT{
int fail;
vector<int> vec;
}tr[N];
int seg;
int to[N],nxt[N],head[N],val[N],rp;
void add_edg(int x,int y,int v){
to[++rp]=y;val[rp]=v;
nxt[rp]=head[x];
head[x]=rp;
}
void ins(char *x,int id){
int len=strlen(x+1);
int now=0;
fo(i,1,len){
int fl=false;
for(int j=head[now];j;j=nxt[j]){
if(val[j]==x[i]-'a'){
now=to[j];fl=true;break;
}
}
if(!fl){
++seg;add_edg(now,seg,x[i]-'a');
now=seg;
}
}
tr[now].vec.push_back(id);
}
}z,f;
int dzn[N],dzm[N],cnz;
int dfn[N],dfm[N],cnf,idf[2005];
void dfs_f(int x){
dfn[x]=++cnf;
for(int i:f.tr[x].vec)idf[i]=cnf;
for(int i=f.head[x];i;i=f.nxt[i]){
int y=f.to[i];
dfs_f(y);
}
dfm[x]=cnf;
}
void dfs_z(int x){
dzn[x]=++cnz;rt[cnz]=rt[cnz-1];
for(int i:z.tr[x].vec)zxs.ins(rt[cnz],rt[cnz],1,cnf,idf[i]);
for(int i=z.head[x];i;i=z.nxt[i]){
int y=z.to[i];
dfs_z(y);
}
dzm[x]=cnz;
}
int n,m,ans;
char s[N],t[N];
signed main(){
// cerr<<(sizeof(z)*2>>20)<<endl;
n=read();
fo(i,1,n){
scanf("%s",s+1);
z.ins(s,i);
reverse(s+1,s+strlen(s+1)+1);
f.ins(s,i);
}
dfs_f(0);dfs_z(0);
m=read();
while(m--){
int ls,lt;
scanf("%s",s+1);ls=strlen(s+1);
scanf("%s",t+1);lt=strlen(t+1);
fo(i,1,ls)s[i]=(s[i]-'a'+ans)%26+'a';
fo(i,1,lt)t[i]=(t[i]-'a'+ans)%26+'a';
reverse(t+1,t+lt+1);bool fl=true;
int nz=0;fo(i,1,ls){
int fla=false;
for(int j=z.head[nz];j;j=z.nxt[j]){
if(z.val[j]==s[i]-'a'){
nz=z.to[j];fla=true;break;
}
}
if(!fla){fl=false;break;}
}
int nf=0;fo(i,1,lt){
int fla=false;
for(int j=f.head[nf];j;j=f.nxt[j]){
if(f.val[j]==t[i]-'a'){
nf=f.to[j];fla=true;break;
}
}
if(!fla){fl=false;break;}
}
if(!fl){printf("%d\n",ans=0);continue;}
printf("%d\n",ans=zxs.query(rt[dzn[nz]-1],rt[dzm[nz]],1,cnf,dfn[nf],dfm[nf]));
}
}
串
发现\(K\)可以放到复杂度中,于是我们直接用主席树维护最大最小值
然后用一个优先队列,不断弹出就好了
然后我就写了一个带\(pushdown\)的主席树,内存炸了
AC_code
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
int read(){
int s=0,t=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')t=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){s=(s<<3)+(s<<1)+ch-'0';ch=getchar();}
return s*t;
}
const int inf=0x3f3f3f3f3f3f3f3f;
const int N=1e5+5;
int n,k,a[N],rt[N];
struct ZXS{
struct POT{
int mx,id,tg,ls,rs;
}tr[N*150];
int seg,mxn,idn;
int newpot(int x){
++seg;tr[seg]=tr[x];
return seg;
}
void pushup(int x){
if(tr[tr[x].ls].mx>tr[tr[x].rs].mx){
tr[x].mx=tr[tr[x].ls].mx;
tr[x].id=tr[tr[x].ls].id;
}
else {
tr[x].mx=tr[tr[x].rs].mx;
tr[x].id=tr[tr[x].rs].id;
}
return ;
}
void pushdown(int x){
tr[x].ls=newpot(tr[x].ls);
tr[x].rs=newpot(tr[x].rs);
tr[tr[x].ls].tg+=tr[x].tg;
tr[tr[x].ls].mx+=tr[x].tg;
tr[tr[x].rs].tg+=tr[x].tg;
tr[tr[x].rs].mx+=tr[x].tg;
// cout<<tr[tr[x].ls].tg<<" "<<tr[tr[x].rs].tg<<endl;
tr[x].tg=0;
}
void build(int &x,int l,int r){
x=++seg;tr[x].id=l;
if(l==r)return ;
int mid=l+r>>1;
build(tr[x].ls,l,mid);
build(tr[x].rs,mid+1,r);
}
void ins(int &x,int l,int r,int ql,int qr,int v){
x=newpot(x);// if(v==1)cout<<l<<" "<<r<<" "<<ql<<" "<<qr<<" "<<tr[x].mx<<" "<<tr[x].tg<<endl;
if(ql<=l&&r<=qr){
tr[x].tg+=v;tr[x].mx+=v;
return ;
}
if(tr[x].tg)pushdown(x);
int mid=l+r>>1;
if(ql<=mid)ins(tr[x].ls,l,mid,ql,qr,v);
if(qr>mid)ins(tr[x].rs,mid+1,r,ql,qr,v);
pushup(x);return ;
}
void query(int x,int l,int r,int ql,int qr){
if(ql<=l&&r<=qr){
if(tr[x].mx>mxn)mxn=tr[x].mx,idn=tr[x].id;
return ;
}
if(tr[x].tg)pushdown(x);
int mid=l+r>>1;
if(ql<=mid)query(tr[x].ls,l,mid,ql,qr);
if(qr>mid)query(tr[x].rs,mid+1,r,ql,qr);
pushup(x);
}
}zxs;
struct node{
int l,r,v;
bool operator < (node a)const{
return v<a.v;
}
};
priority_queue<node> q;
map<int,int> mp;
int lst[N];
signed main(){
n=read();k=read();
zxs.build(rt[0],1,n);
fo(i,1,n){
a[i]=read();
if(mp.find(a[i])!=mp.end())lst[i]=mp[a[i]];
mp[a[i]]=i;rt[i]=zxs.newpot(rt[i-1]);
zxs.ins(rt[i],1,n,lst[i]+1,i,a[i]);
zxs.mxn=-inf;zxs.query(rt[i],1,n,1,i);
q.push(node{zxs.idn,i,zxs.mxn});
}
// zxs.mxn=-inf;zxs.query(rt[6],1,n,4,4);
while(--k){
node now=q.top();q.pop();
zxs.ins(rt[now.r],1,n,now.l,now.l,-inf-now.v);
zxs.mxn=-inf;zxs.query(rt[now.r],1,n,1,now.r);
if(zxs.mxn!=inf)q.push(node{zxs.idn,now.r,zxs.mxn});
}
printf("%lld\n",q.top().v);
}
这个是没有\(pushdown\)的
AC_code
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
int read(){
int s=0,t=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')t=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){s=(s<<3)+(s<<1)+ch-'0';ch=getchar();}
return s*t;
}
const ll inf=0x3f3f3f3f3f3f3f3f;
const int N=1e5+5;
int n,k,a[N],rt[N];
struct ZXS{
struct POT{
ll mx,tg;
int id,ls,rs;
}tr[N*75];
int seg,idn;ll mxn;
int newpot(int x){
++seg;tr[seg]=tr[x];
return seg;
}
void pushup(int x){
if(tr[tr[x].ls].mx>tr[tr[x].rs].mx){
tr[x].mx=tr[tr[x].ls].mx+tr[x].tg;
tr[x].id=tr[tr[x].ls].id;
}
else {
tr[x].mx=tr[tr[x].rs].mx+tr[x].tg;
tr[x].id=tr[tr[x].rs].id;
}
return ;
}
void build(int &x,int l,int r){
x=++seg;tr[x].id=l;
if(l==r)return ;
int mid=l+r>>1;
build(tr[x].ls,l,mid);
build(tr[x].rs,mid+1,r);
}
void ins(int &x,int l,int r,int ql,int qr,ll v){
x=newpot(x);
if(ql<=l&&r<=qr){
tr[x].tg+=v;tr[x].mx+=v;
return ;
}
int mid=l+r>>1;
if(ql<=mid)ins(tr[x].ls,l,mid,ql,qr,v);
if(qr>mid)ins(tr[x].rs,mid+1,r,ql,qr,v);
pushup(x);return ;
}
void query(int x,int l,int r,int ql,int qr,ll sum){
if(ql<=l&&r<=qr){
if(tr[x].mx+sum>mxn)mxn=tr[x].mx+sum,idn=tr[x].id;
return ;
}
int mid=l+r>>1;
if(ql<=mid)query(tr[x].ls,l,mid,ql,qr,sum+tr[x].tg);
if(qr>mid)query(tr[x].rs,mid+1,r,ql,qr,sum+tr[x].tg);
pushup(x);
}
}zxs;
struct node{
int l,r;ll v;
bool operator < (node a)const{
return v<a.v;
}
};
priority_queue<node> q;
map<ll,int> mp;
int lst[N];
signed main(){
n=read();k=read();
zxs.build(rt[0],1,n);
fo(i,1,n){
a[i]=read();
if(mp.find(a[i])!=mp.end())lst[i]=mp[a[i]];
mp[a[i]]=i;rt[i]=rt[i-1];
zxs.ins(rt[i],1,n,lst[i]+1,i,a[i]);
zxs.mxn=-inf;zxs.query(rt[i],1,n,1,i,0);
q.push(node{zxs.idn,i,zxs.mxn});
}
while(--k){
node now=q.top();q.pop();
zxs.ins(rt[now.r],1,n,now.l,now.l,-inf-now.v);
zxs.mxn=-inf;zxs.query(rt[now.r],1,n,1,now.r,0);
if(zxs.mxn!=inf)q.push(node{zxs.idn,now.r,zxs.mxn});
}
printf("%lld\n",q.top().v);
}
QQ:2953174821