【省選模擬】20/06/11

AA

  • 定義深度爲到根的邊權和,考慮按深度 dpdp,顯然深度小的放的是出現次數較多的數
    即放得是一個後綴,記錄 dpi,a,b,cdp_{i,a,b,c} 表示到第 ii 層當前層有 aa 個,下一層可以放 bb 個,選的後綴爲 cc 的最小值,枚舉多少個後綴放當前層,對應轉移到 dpi+1,b+(at),at,c+tdp_{i+1,b+(a-t),a-t,c+t},係數是 iti*t
    係數可以提前計算,於是可以壓掉層數一維,對應轉移到 dpb+at,at,c+tdp_{b+a-t,a-t,c+t},係數是 i=1cai\sum_{i=1}^ca_i
    考慮將後綴一個一個加入,枚舉是當前層還是下一層,到當前層是一個完全揹包,複雜度 O(n3)O(n^3)
#include<bits/stdc++.h>
#define cs const
#define pb push_back
using namespace std;
typedef long long ll;
cs int N = 755;
int n; ll c[N], dp[2][N][N]; 
void ckmin(ll &a, ll b){ if(a > b) a = b; }
int main(){
	#ifdef FSYolanda
	freopen("1.in","r",stdin);
	#endif
	scanf("%d",&n);
	for(int i=1; i<=n; i++) scanf("%lld",&c[i]);
	sort(c+1,c+n+1);
	for(int i=1; i<=n; i++) c[i]+=c[i-1];
	int now=0, nxt=1; 
	memset(dp[now],0x3f,sizeof(dp[now]));
	dp[now][1][1] = c[n];
	for(int i=n; i>=1; i--){
		memset(dp[nxt],0x3f,sizeof(dp[nxt]));
		for(int j=0; j<=i; j++)
		for(int k=0; j+k<=i; k++)
		ckmin(dp[now][j+k][j],dp[now][j][k]+c[i]);
		for(int j=1; j<=i; j++)
		for(int k=0; j+k<=i; k++)
		ckmin(dp[nxt][j-1][k],dp[now][j][k]);
		swap(now,nxt);
	} cout<<dp[now][0][0]; return 0;
}

BB

  • 考慮兩個 1111 直接不可能到達,狀態較少,可以通過
#include<bits/stdc++.h>
#define cs const
#define pb push_back
using namespace std;
typedef long long ll;
cs int N = 80;
int Mod, iv2, iv4;
int add(int a, int b){ return a + b >= Mod ? a + b - Mod : a + b; }
int dec(int a, int b){ return a - b < 0 ? a - b + Mod : a - b; }
int mul(int a, int b){ return 1ll * a * b % Mod; }
void Add(int &a, int b){ a = add(a,b); }
void Mul(int &a, int b){ a = mul(a,b); }
void Dec(int &a, int b){ a = dec(a,b); }
int ksm(int a, int b){ int as=1; for(;b;b>>=1,Mul(a,a)) if(b&1) Mul(as,a); return as; }
int n; typedef bitset<N> bs;
namespace table{
	cs int M = 19260817;
	int fi[M], nxt[M], v[M], ec; bs w[M];
	void ins(bs x, int vl){
		int t=0; for(int i=0; i<n; i++) t=(ll)(t*31+x[i])%M;
		nxt[++ec]=fi[t]; fi[t]=ec, swap(w[ec],x), v[ec]=vl;
		t=0; for(int i=n-1;~i;i--) t=(ll)(t*31+x[i])%M;
		nxt[++ec]=fi[t]; fi[t]=ec, swap(w[ec],x), v[ec]=vl;
	} 
	int ask(bs x){
		int t=0; for(int i=0; i<n; i++) t=(ll)(t*31+x[i])%M;
		for(int e=fi[t];e;e=nxt[e])
		if(w[e]==x) return v[e]; return -1;
	}
}
void cover(bs&x){
	int l=n+1,r=-1;
	for(int i=1;i+1<n;i++)
	if(x[i]&&x[i+1])l=min(l,i),r=max(r,i);
	for(int i=l; i<=r+1; i++) x.set(i);
}
int dfs(bs x){
	if(x.test(0)) return 0;
	x.set(0); cover(x); 
	int t = table::ask(x);
	if(~t) return t;
	int ans = 0; 
	bs nx = x>>1; if(x.test(0)) nx.set(n-1);
	Add(ans,dfs(nx));
	nx = x>>2; if(x.test(0)) nx.set(n-2); if(x.test(1)) nx.set(n-1);
	Add(ans,dfs(nx));
	nx = x<<1; if(x.test(n-1)) nx.set(0);
	Add(ans,dfs(nx));
	nx = x<<2; if(x.test(n-1)) nx.set(1); if(x.test(n-2)) nx.set(0);
	Add(ans,dfs(nx));
	Mul(ans,iv4); Add(ans,1);
	return ans;
}
int main(){
	#ifdef FSYolanda
	freopen("1.in","r",stdin);
	#endif
	scanf("%d%d",&n,&Mod); 
	iv2 = (Mod+1)>>1; iv4 = mul(iv2,iv2);
	if(n==1) return puts("1"),0; 
	cout << dfs(bs());
	return 0;
}

CC

  • 要維護當前 pampam 上一條鏈的 lensize\sum len*size
    把串離線下來,預處理每個點向前向後的最長迴文前後綴,實際的最長迴文前後綴需要在後綴樹上跳到對應的長度,加入一個點對應的鏈修改,詢問是一個鏈求和,用樹剖解決
    lcalca 的貢獻特殊處理,若二者的 lcplcp 恰是最長公共迴文前綴,則 lcalca 的貢獻可以被算到,否則不能被算到
#include<bits/stdc++.h>
#define cs const
#define pb push_back
using namespace std;
typedef long long ll;
namespace IO{
	cs int Rlen=1<<22|1;
	inline char gc(){
		static char buf[Rlen],*p1,*p2;
		(p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin));
		return p1==p2?EOF:*p1++;
	} int gi(){
		int x=0; char c=gc(); bool f=false;
		while(!isdigit(c)) f=c=='-',c=gc();
		while(isdigit(c)) x=(((x<<2)+x)<<1)+(c^48), c=gc();
		return f?-x:x;
	} int opt(){
		int x=0; char c=gc(),t; while(isspace(c)) c=gc();
		if(c=='t') x=2; while(true){
			t=gc(); if(t=='r'&&c!='t') break;
			if(t=='l') break; c=t;
		} if(t=='r') ++x; return x;
	}
} using namespace IO;
cs int N = 4e5 + 50;
struct my{ int opt, c, l1, r1, l2, r2; };
int n, m, a[N], b[N]; my t[N];
int pl[N], pr[N], L, R;
vector<int> G[N];
namespace PAM{
	int las, nd, pt, sz[N], len[N], lk[N], ch[N][26]; 
	int jmp(int x){ while(a[pt-len[x]-1]!=a[pt]) x=lk[x]; return x; }
	int extend(int c){
		++pt; int p = jmp(las); 
		if(!ch[p][c]){
			int u = ++nd; len[u]=len[p]+2;
			lk[u] = ch[jmp(lk[p])][c]; ch[p][c] = u;
		} return las = ch[p][c];
	}
	void init(){ las = nd = 1; lk[0] = 1; len[1] = -1; } 
} using PAM :: len;
int in[N], dfn, son[N], sz[N], fa[N], dep[N], top[N], ps[N];
void pre_dfs(int u){
	sz[u] = 1; for(int e=0,v;e<(int)G[u].size();e++){
		v=G[u][e]; dep[v]=dep[u]+1;
		fa[v]=u; pre_dfs(v); sz[u]+=sz[v];
		if(sz[son[u]]<sz[v]) son[u] = v;
	} 
}
void sub_dfs(int u, int tp){
	ps[in[u]=++dfn]=u; top[u]=tp;
	if(son[u]) sub_dfs(son[u],tp);
	for(int e=0,v;e<(int)G[u].size();e++)
	if((v=G[u][e])!=son[u]) sub_dfs(v,v);
}
namespace SGT{
	cs int N = ::N << 2;
	#define mid ((l+r)>>1)
	ll sm[N], vl[N], tg[N];
	void up(int x){ sm[x]=sm[x<<1]+sm[x<<1|1]; }
	void put(int x, ll v){ tg[x]+=v; sm[x]+=v*vl[x]; }
	void down(int x){ if(tg[x])put(x<<1,tg[x]),put(x<<1|1,tg[x]),tg[x]=0; }
	void build(int x, int l, int r){
		if(l==r) return vl[x]=len[ps[l]],void();
		build(x<<1,l,mid); build(x<<1|1,mid+1,r);
		vl[x]=vl[x<<1]+vl[x<<1|1];
	} void mdf(int x, int l, int r, int L, int R){
		if(L<=l&&r<=R) return put(x,1),void(); down(x);
		if(L<=mid) mdf(x<<1,l,mid,L,R);
		if(R>mid) mdf(x<<1|1,mid+1,r,L,R); up(x);
	} ll qry(int x, int l, int r, int L, int R){
		if(L<=l&&r<=R) return sm[x]; down(x); ll ans=0;
		if(L<=mid) ans+=qry(x<<1,l,mid,L,R);
		if(R>mid) ans+=qry(x<<1|1,mid+1,r,L,R); return ans;
	}
	#undef mid
}
void upt(int x){ while(x) SGT::mdf(1,1,dfn,in[top[x]],in[x]),x=fa[top[x]]; }
int jmp(int x, int lm){
	while(len[top[x]]>lm) x=fa[top[x]];
	int l=in[top[x]],r=in[x];
	while(l<r){
		int mid=(l+r+1)>>1;
		if(len[ps[mid]]>lm) r=mid-1;
		else l=mid;
	} return ps[l];
}
int lca(int u, int v){
	while(top[u]^top[v]){
		if(dep[top[u]]<dep[top[v]]) swap(u,v);
		u=fa[top[u]];
	} return in[u]<in[v]?u:v;
}
ll qry(int u, int v){
	ll ans = 0;
	while(top[u]^top[v]){
		if(dep[top[u]]<dep[top[v]]) swap(u,v);
		ans += SGT::qry(1,1,dfn,in[top[u]],in[u]);
		u = fa[top[u]];
	} if(in[u]>in[v]) swap(u,v);
	ans += SGT::qry(1,1,dfn,in[u],in[v]);
	return ans;
}
ll askl(my t){
	int u = jmp(pr[t.r1],t.r1-t.l1+1);
	int v = jmp(pr[t.r2],t.r2-t.l2+1);
	int pt = lca(u,v), lm = len[pt]; ll ans = qry(u,v);
	if(lm < t.r1 - t.l1 + 1 && lm < t.r2 - t.l2 + 1 && a[t.r1-lm] == a[t.r2-lm]) 
	ans -= qry(pt,pt); return ans;
}
ll askr(my t){
	int u = jmp(pl[t.l1],t.r1-t.l1+1);
	int v = jmp(pl[t.l2],t.r2-t.l2+1);
	int pt = lca(u,v), lm = len[pt];ll ans = qry(u,v); 
	if(lm <t.r1 - t.l1 + 1 && lm < t.r2 - t.l2 + 1 && a[t.l1+lm] == a[t.l2+lm])
	ans -= qry(pt,pt); return ans;
}
int main(){
	#ifdef FSYolanda
	freopen("1.in","r",stdin);
	#endif
	n=gi(), m=gi(); 
	for(int i=1; i<=n; i++) b[i]=gi();
	for(int i=1,op; i<=m; i++){
		op=opt(); 
		if(op==0) t[i]=(my){op,gi()};
		if(op==1) t[i]=(my){op,gi()};
		if(op>=2) t[i]=(my){op,0,gi(),gi(),gi(),gi()};
	} 
	for(int i=m,l=0; i>=1; i--){
		if(t[i].opt==0) ++l; if(t[i].opt>=2) 
		t[i].l1+=l,t[i].l2+=l,t[i].r1+=l,t[i].r2+=l;
	}
	int len = 0;
	for(int i=m; i>=1; i--) 
	if(t[i].opt==0) a[++len] = t[i].c; L = len+1;
	for(int i=1; i<=n; i++) a[++len] = b[i]; R = len;
	for(int i=1; i<=m; i++)
	if(t[i].opt==1) a[++len] = t[i].c;
	n = len; a[n+1] = a[0] = -1;
	PAM :: init();
	for(int i=1; i<=n; i++) pr[i] = PAM :: extend(a[i]);
	reverse(a+1,a+n+1); PAM :: las = 1; PAM :: pt = 0;
	for(int i=1; i<=n; i++) pl[i] = PAM :: extend(a[i]);
	reverse(a+1,a+n+1);
	reverse(pl+1,pl+n+1);
	for(int i=2; i<=PAM::nd; i++) 
	G[PAM::lk[i]?PAM::lk[i]:1].pb(i);
	PAM :: len[1] = 0; pre_dfs(1); sub_dfs(1,1);
	SGT :: build(1,1,dfn);
	for(int i=L; i<=R; i++)
	upt(jmp(pr[i],i-L+1));
	for(int i=1; i<=m; i++){
		if(t[i].opt==0) --L, upt(jmp(pl[L],R-L+1));
		if(t[i].opt==1) ++R, upt(jmp(pr[R],R-L+1));
		if(t[i].opt==2) cout<<askl(t[i])<<'\n';
		if(t[i].opt==3) cout<<askr(t[i])<<'\n';
	}
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章