T1 活動投票 0Pts
原題 yyy loves Maths VI (mode)
摩爾投票板子。
這題卡了不加速的 cin 導致我一分沒拿。
點選檢視程式碼
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int n,x,now,cnt;
int main(){
ios::sync_with_stdio(0);
cin>>n;
while(n--){
cin>>x;
if(!cnt)now=x;
if(x==now)cnt++;
else cnt--;
}
cout<<now;
return 0;
}
T2 序列 10Pts
原題 不無聊的序列 Non-boring sequences
如果暴力列舉子串的話,複雜度為 \(O(n^4)\),且“列舉子串”的 \(n^2\) 顯然無法最佳化;
所以改變思路,考慮每個點;
我們記錄一下一個數上一次出現的位置和下一次出現的位置,這樣可以判斷在 \(l\) 到 \(r\) 中一個數是否僅出現一次;
如果該序列不無聊,那麼對於任意一個序列 \([l,r]\),都有一個 \(a_k\) 是唯一存在的數,那麼在 \([l,r]\) 中包含該數的序列都不無聊,遞迴求解 \([l,k-1]\) 和 \([k+1,r]\) 即可。
點選檢視程式碼
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+5;
int T,n;
int a[N],pre[N],nxt[N];
map<int,int> mp;
bool solve(int L,int R){
if(L>=R)return 1;
int l=L,r=R;
while(l<=r){
if(pre[l]<L&&nxt[l]>R)return solve(L,l-1)&&solve(l+1,R);
if(pre[r]<L&&nxt[r]>R)return solve(L,r-1)&&solve(r+1,R);
l++;r--;
}
return 0;
}
int main(){
cin>>T;
while(T--){
mp.clear();
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
nxt[i]=n+1;
pre[i]=mp[a[i]],nxt[pre[i]]=i;
mp[a[i]]=i;
}
cout<<(solve(1,n)?"non-boring":"boring")<<"\n";
}
return 0;
}
T3 Legacy 40Pts
原題 Legacy
線段樹最佳化建圖板子。
暴力建圖的時空都嚴重不對,所以我們要線段樹最佳化建圖。
開兩顆線段樹,一顆記錄入邊,一顆記錄出邊,相同點之間連權值為 \(0\) 的邊,隨後直接連邊跑就行。
點選檢視程式碼
#include<bits/stdc++.h>
#define int ll
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N=3e6+5;
const int K=5e5;
int n,m,s,op,x,y,z,l,r,w,a[N],dis[N],vis[N];
struct edge{
int next,to,w;
}e[N];
int h[N],cnt;
void add(int u,int v,int w){
e[++cnt]={h[u],v,w};
h[u]=cnt;
}
void build(int p,int l,int r){
if(l==r){
a[l]=p;
return;
}
int mid=(l+r)>>1;
add(p,p<<1,0);add(p,p<<1|1,0);
add((p<<1)+K,p+K,0);add((p<<1|1)+K,p+K,0);
build(p<<1,l,mid);
build(p<<1|1,mid+1,r);
}
void update(int p,int l,int r,int L,int R,int v,int w,int op){
if(L<=l&&r<=R){
if(op==2)add(v+K,p,w);
else add(p+K,v,w);
return;
}
int mid=(l+r)>>1;
if(L<=mid)update(p<<1,l,mid,L,R,v,w,op);
if(R>mid)update(p<<1|1,mid+1,r,L,R,v,w,op);
}
void dij(int s){
priority_queue<pii> q;
memset(dis,0x3f,sizeof(dis));
dis[s]=0;
q.push({0,s});
while(!q.empty()){
int u=q.top().second;
q.pop();
if(vis[u])continue;
vis[u]=1;
for(int i=h[u];i;i=e[i].next){
int to=e[i].to;
if(dis[to]>dis[u]+e[i].w){
dis[to]=dis[u]+e[i].w;
q.push({-dis[to],to});
}
}
}
}
main(){
cin>>n>>m>>s;
build(1,1,n);
for(int i=1;i<=n;i++){
add(a[i],a[i]+K,0);
add(a[i]+K,a[i],0);
}
for(int i=1;i<=m;i++){
cin>>op;
if(op==1){
cin>>x>>y>>z;
add(a[x]+K,a[y],z);
}
else{
cin>>x>>l>>r>>w;
update(1,1,n,l,r,a[x],w,op);
}
}
dij(a[s]+K);
for(int i=1;i<=n;i++){
if(dis[a[i]]==0x3f3f3f3f3f3f3f3f)dis[a[i]]=-1;
cout<<dis[a[i]]<<" ";
}
return 0;
}
T4 DP搬運工1 26Pts
題面
聽得不是很懂,搬一下 @HaneDaniko 的題解:
膜拜了。
點選檢視程式碼
#include<bits/stdc++.h>
#define int ll
using namespace std;
typedef long long ll;
const int N=55;
const int mod=998244353;
int f[N][N][N*N];
int n,K;
main(){
cin>>n>>K;
f[1][0][0]=1;
for(int i=2;i<=n;i++){
for(int j=0;j<=n-i+1;j++){
for(int k=0;k<=K;k++){
if(!f[i-1][j][k])continue;
if(j){
f[i][j][k+i]=(f[i][j][k+i]+f[i-1][j][k]*2%mod*j%mod)%mod;
f[i][j+1][k]=(f[i][j+1][k]+f[i-1][j][k]*j%mod)%mod;
f[i][j-1][k+2*i]=(f[i][j-1][k+2*i]+f[i-1][j][k]*j%mod)%mod;
}
f[i][j][k+i]=(f[i][j][k+i]+f[i-1][j][k]*2%mod)%mod;
f[i][j+1][k]=(f[i][j+1][k]+f[i-1][j][k]*2%mod)%mod;
}
}
}
int ans=0;
for(int i=0;i<=K;i++){
ans=(ans+f[n][0][i])%mod;
}
cout<<ans;
return 0;
}