好像還有好多沒寫的
A. Mortis
賽時思路是正解,但有一個判斷想了但出鍋了。。。
\(n\) 個數的序列 \(n-1\) 次肯定能換完,一次操作最多貢獻 2,找出貢獻2的操作個數減去即可
有一次操作匹配兩個,兩次操作匹配三個,三個操作匹配四個,三種情況,記個數都跑一遍即可
點選檢視程式碼
#include<bits/stdc++.h>
const int maxn=2e5+10;
using namespace std;
int n,a[maxn],l[10],r[10],cnt[10][10],sum[10],ans,x,z;
int main()
{
// freopen("sample.in","r",stdin);
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
sum[a[i]]++;
}
for(int i=1;i<=4;i++)
{
if(sum[i])
{
l[i]=r[i-1]+1;
r[i]=l[i]+sum[i]-1;
}
else
{
r[i]=r[i-1];
l[i]=r[i]+1;
}
}
// cout<<r[4]<<endl;
for(int i=1;i<=4;i++)
{
for(int j=l[i];j<=r[i];j++)
{
if(sum[i])cnt[i][a[j]]++;
}
}
// int c=0;
// for(int i=1;i<=4;i++)
// for(int j=i;j<=4;j++)c+=cnt[i][j];
// cout<<c<<endl;
int o=0;
ans=n-1;
for(int i=1;i<=4;i++)x+=cnt[i][i];
for(int i=1;i<=4;i++)
{
for(int j=i;j<=4;j++)
{
if(sum[i]>0&&sum[j]>0)
{
int f=min(cnt[i][j],cnt[j][i]);
o+=f;
ans-=f;
cnt[i][j]-=f;
if(i!=j)cnt[j][i]-=f;
// cout<<cnt[i][j]<<" "<<cnt[j][i]<<endl;
}
}
}
// for(int i=1;i<=4;i++)
// for(int j=1;j<=4;j++)
// cout<<cnt[i][j]<<" ";
for(int i=1;i<=4;i++)
{
for(int j=1;j<=4;j++)
{
for(int k=1;k<=4;k++)
{
int f=min(min(cnt[i][j],cnt[j][k]),cnt[k][i]);
ans-=f;
z+=f;
cnt[i][j]-=f;
cnt[j][k]-=f;
cnt[k][i]-=f;
}
}
}
int u=0;
for(int i=1;i<=4;i++)
for(int j=1;j<=4;j++)
for(int k=1;k<=4;k++)
for(int e=1;e<=4;e++)
{
int f=min(min(cnt[i][j],cnt[j][k]),min(cnt[k][e],cnt[e][i]));
ans-=f;
u+=f;
cnt[i][j]-=f;
cnt[j][k]-=f;
cnt[k][e]-=f;
cnt[e][i]-=f;
}
// for(int i=1;i<=4;i++)
// for(int j=1;j<=4;j++)
// cout<<cnt[i][j]<<" ";
// cout<<n<<" "<<ans<<" "<<z<<" "<<o<<endl;
// cout<<(n+u-1-x-ans)*2+x+z<<endl;
if((n+u-1-x-ans)*2+x+z==n)ans++;
cout<<ans;
return 0;
}
/*
13
3 3 1 1 1 3 3 3 4 2 4 2 2
*/
C. 嘉然今天吃什麼
我感覺我現在急需一個資料結構大佬來傳授一下程式碼能力。。
賽事我打完暴力,開始考慮最大值的貢獻,發現只需要找一個鏈上的最大值即可,然後我就開始想如何 \(log n\) 內求出
最大值,但我只會 \(n^2\) 的。。。很惱,講 \(trie\) 樹時基本沒聽,根本沒想起來有這玩意。。。
用 \(0,1,trie\) 樹,每次把除了這個點子樹之外的點都插入 \(trie\) 樹,倒著遍歷可以使每個點只插一次,直接查即可
點選檢視程式碼
#include<bits/stdc++.h>
#define ll long long
const int maxn=5e5+10;
using namespace std;
int n,head[maxn],to[maxn],nxt[maxn],tot,cnt;
int t[maxn*65][2],fa[maxn];
ll a[maxn],now,ans[maxn];
inline void add(int x,int y)
{
to[++tot]=y;
nxt[tot]=head[x];
head[x]=tot;
}
void insert(ll x)
{
int p=0;
for(int i=63;i>=0;i--)
{
int c=x>>i&1;
if(!t[p][c])t[p][c]=++cnt;
p=t[p][c];
}
}
ll query(ll x)
{
ll res=0,p=0;
for(int i=63;i>=0;i--)
{
int c=x>>i&1;
if(t[p][c^1])res=res*2+1,p=t[p][c^1];
else res=res*2,p=t[p][c];
}
if(res>now)now=res;
return res;
}
inline void lsx(int x)
{
insert(a[x]);
query(a[x]);
for(int i=head[x];i;i=nxt[i])
{
int y=to[i];
lsx(y);
}
}
void dfs(int u,int p)
{
if(!u)return ;
dfs(fa[u],u);
// cout<<u<<" "<<now<<"!"<<endl;
ans[u]=now;
insert(a[u]);
query(a[u]);
for(int i=head[u];i;i=nxt[i])
{
int y=to[i];
if(y!=p)lsx(y);
}
}
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
cin>>n;
fill(ans+1,ans+1+n,-1);
for(int i=1;i<n;i++)
{
int x;
cin>>x;
fa[i+1]=x;
add(x,i+1);
}
for(int i=1;i<=n;i++)cin>>a[i],insert(a[i]);
ll x=0,y=0,res=0;
for(int i=1;i<=n;i++)
{
ll temp=query(a[i]);
if (temp>res)
{
res=temp;
x=a[i],y=temp^a[i];
}
}
ll xx=0,yy=0;
for(int i=1;i<=n;i++)
if(a[i]==x) xx=i;
else if(a[i]==y) yy=i;
memset(t,0,sizeof t),cnt=0,now=0;
dfs(xx,0);
memset(t,0,sizeof t),cnt=0,now=0;
dfs(yy,0);
for(int i=1;i<=n;i++)
cout<<(ans[i]>=0?ans[i]:res)<<'\n';
return 0;
}