2022.4.10普及組模擬
A 排座位
沒有任何難度的大水題
想複雜了。如果只能是兩個相鄰的位置交換自然要求逆序對,但是這個題可以隨便換,所以我們亂搞。最終的目標就是把 \(1\) 換到第一個位置, \(2\) 換到第二個位置,以此類推
如果 \(data_i=i\) 就不操作,如果 $data_i != i $ 且 \(data_{pos} = i\) 則交換。很顯然的做法,但是乍一看貌似無法保證交換次數最小,所以有另一個很嚴謹的做法
\(Code\)
#include<bits/stdc++.h> using namespace std; const int maxn=1000000+5; inline int read(){ int x=0;char c=getchar(); while(c<'0'||c>'9')c=getchar(); while(c>='0'&&c<='9'){ x=(x<<1)+(x<<3)+(c^'0');c=getchar(); } return x; } int data[maxn],pos[maxn]; int n; int main(){ freopen("seat.in","r",stdin); freopen("seat.out","w",stdout); n=read(); for(int i=1;i<=n;++i){ data[i]=read(); pos[data[i]]=i; } int ans=0; for(int i=1;i<=n;++i){ if(data[i]!=i){ pos[data[i]]=pos[i]; swap(data[i],data[pos[i]]); ans++; } } printf("%d\n",ans); return 0; }
B 夢中的學校(原題金字塔,《演算法競賽進階指南》區間DP部分)
對於一個字串 \(S_l - S_r\)可能會有多種情況,所以考慮區間DP。定義狀態 \(f_{i,j}\) 為 \(S_l - S_r\) 的情況數。
我們只考慮其構成一顆樹的情況,所以 \(S_l!=S_r\) 的情況是不合法,dfs肯定要從根進去再從根出來。
如果 \(l=r\) 很顯然方案數為1
為了不重複計數,只考慮該範圍中第一顆子樹的範圍,列舉斷點 \(k\) ,\(l-r\) 被分為 \(l+1--k-1\) 和 \(k--r-1\)兩部分,\(k\) 不相同,第一顆子樹大小也就不相同,就不可能產生重複的結構,則有方程
\(f_{i,j}\)=\(f_{i,j} + f_{i+1,k-1} * f_{k,j-1}\)
狀態之間遵循加法原理而子狀態之間遵循乘法原理
Code
int solve(int l,int r){ if(l>r)return 0; if(S[l]!=S[r])return f[l][r]=0; if(l==r)return f[l][r]=1; if(f[l][r]!=-1)return f[l][r]; f[l][r]=0; for(int k=l+2;k<=r;++k){ f[l][r]=(f[l][r]+1ll*solve(l+1,k-1)*solve(k,r))%mod; } return f[l][r]; } printf("%d\n",solve(1,strlen(S+1)));
C 激流突進(SCOI2011糖果)
顯然是一個差分約束系統
如果\(u>v\),則\(<u,v>=1\)
如果\(u<v\),則\(<v,u>=1\)
如果\(u=v\),則\(<u,v>=<u,v>=0\)
如果\(u<=v\),則\(<v,u>=0\)
如果\(u>=v\),則\(<u,v>=0\)
如果A>B>C,則<B,A>=<C,B>=<C,A>=1,為了使結果正確,建完圖之後跑最長路。
建完圖之後很有可能不完全,設一個解\(X_0=0\),由於其他的解都是正解,很顯然有\(\forall i\in [1,n]\),都有\(X_i>=X_0\),即\(X_i-X_0>=0\),0向所有的點連一條權值為0的邊即可
不成立的情況:
如果A>B,B>C,C>A,顯然不成立,而且建圖後出現環,可以用topo排序處理。最長路演算法常用spfa,且spfa跑最長路可以判正環,所以用spfa處理
如果A>A 或 A<A ,顯然不成立
這樣處理完之後貌似就沒什麼問題,但是除了正環以外還有另外一種環,A=B=C,邊權都為0,所以spfa掃它沒啥意義,所以連完1,3,5三種情況後Tarjan縮點,再連2,4情況的邊
struct Graph{
struct edge{
int to,next,dis;
}e[maxn*5];
int head[maxn],len;
void Insert(int x,int y,int dis){
e[++len].to=y;e[len].dis=dis;e[len].next=head[x],head[x]=len;
}
bool vis[maxn];
long long cnt[maxn],d[maxn];
bool spfa(int u){
memset(d,0xf3,sizeof(d));
queue<int>q;
q.push(u);
d[u]=1;
vis[u]=1;
cnt[u]=1;
while(!q.empty()){
int x=q.front();q.pop();vis[x]=0;
for(int i=head[x];i;i=e[i].next){
int v=e[i].to;
if(d[v]<d[x]+e[i].dis){
d[v]=d[x]+e[i].dis;
if(!vis[v]){
q.push(v);
cnt[v]++;
vis[v]=1;
if(cnt[v]>n){
return 1;
}
}
}
}
}
return 0;
}
}G;
void work(){
n=read(),m=read();
bool f=0;
for(int i=1;i<=m;++i){
int op=read(),x=read(),y=read();
if(op==1)G.Insert(x,y,0),G.Insert(y,x,0);
if(op==2){if(x==y)f=1;G.Insert(x,y,1);}
if(op==3)G.Insert(y,x,0);
if(op==4){if(x==y)f=1;G.Insert(y,x,1);}
if(op==5)G.Insert(x,y,0);
}
if(f){
printf("-1\n");return;
}
for(int i=n;i>0;--i)G.Insert(0,i,0);//玄學優化
f=G.spfa(0);
if(f){
printf("-1\n");return;
}
long long ans=0;
for(int i=1;i<=n;++i){
ans+=G.d[i];
}
printf("%lld\n",ans);
}
int main(){
work();
return 0;
}
D 獎學金
先按照成績排序,列舉每一個數作為中位數,答案為\(money_i\)+前n/2最小值之和+後n/2最小值之和。最小值之和用優先佇列維護即可
賽時十分鐘打了個線段樹,每次列舉重新建樹,暴力求最值 \(60pts\)。
Code
int data[maxn],pos[maxn];
struct Pig{
long long cs,mo;
}pig[maxn];
bool cmp(Pig x,Pig y){
return x.cs<y.cs;
}
int n,c,F;
int f[maxn],g[maxn];//f[i] i為中位數前n/2最小值的和, g[i] i為中位數後n/2最小值的和
void work(){
priority_queue<long long>q;
long long sum=0;
for(int i=1;i<=n/2;++i){
q.push(pig[i].mo);sum+=pig[i].mo;
}
for(int i=n/2+1;i<=c-n/2;++i){
f[i]=sum;
if(pig[i].mo<q.top()){sum-=q.top();q.pop();q.push(pig[i].mo);sum+=pig[i].mo;}
}
q=priority_queue<long long>();sum=0;
for(int i=c;i>=c-n/2+1;--i){
q.push(pig[i].mo);sum+=pig[i].mo;
}
for(int i=c-n/2;i>=n/2+1;--i){
g[i]=sum;
if(pig[i].mo<q.top()){sum-=q.top();q.pop();q.push(pig[i].mo);sum+=pig[i].mo;}
}
}
int main(){
freopen("money.in","r",stdin);
freopen("money.out","w",stdout);
n=read(),c=read(),F=read();
for(int i=1;i<=c;++i){
pig[i].cs=read(),pig[i].mo=read();
}
sort(pig+1,pig+c+1,cmp);
long long ans=-1;
work();
for(int i=c-n/2;i>=n/2+1;--i){
if(f[i]+g[i]+pig[i].mo<=F){
ans=pig[i].cs;break;
}
}
printf("%lld\n",ans);
return 0;
}