Codeforces Round #612 (Div. 2)
C. Garland
題意:大概就是給你一個n排列,有些位置被拿走了,變成了零,你現在需要任意放回去,新的排列產生一個權值:
這個位置和前一個位置的數字的奇偶性不一樣 就會產生一個權值。
現問你如何重新分配0位置使得權值最小。
dp[i][j][k][z] i位置,奇偶性爲j 時剩餘奇數個數爲k,剩餘偶數個數爲z時的 最小權值。
賽時想到了這個狀態方程,無奈轉移方程一直寫不出,反應了我的dp水平還是很差。。賽後冷靜下來,仔細想了想,嗯做出來了。
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=(b);++i)
#define mem(a,x) memset(a,x,sizeof(a))
#define pb push_back
#define pi pair<int, int>
#define mk make_pair
using namespace std;
typedef long long ll;
const int N=1e2+10,inf=0x3f3f3f3f;
int a[N],n,vis[N],s1,s2;
int dp[N][2][N][N];
int main()
{
cin>>n;
vector<int>G;
rep(i,1,n) {
scanf("%d",&a[i]);
vis[a[i]]=1;
}
rep(i,1,n) {
if(vis[i]) continue;
if(i%2) s1++;
else s2++;
}
memset(dp,inf,sizeof(dp));
dp[0][0][s1][s2]=0;
dp[0][1][s1][s2]=0;
int id=1;
if(a[1]==0){
dp[1][0][s1][s2-1]=0;
dp[1][1][s1-1][s2]=0;
}
else {
if(a[1]%2==0)
dp[1][0][s1][s2]=0;
else
dp[1][1][s1][s2]=0;
}
rep(i,2,n){
if(a[i]==0){
rep(jj,0,1)
rep(j,0,1)
rep(k,0,s1)
rep(z,0,s2){
if(j!=jj) {
if(j==0)
{
if(z-1>=0)
dp[i][j][k][z-1]=min(dp[i][j][k][z-1],dp[i-1][jj][k][z]+1);
}
else {
if(k-1>=0)
dp[i][j][k-1][z]=min(dp[i][j][k-1][z],dp[i-1][jj][k][z]+1);
}
}
else {
if(j==0) {
if(z-1>=0)
dp[i][j][k][z-1]=min(dp[i][j][k][z-1],dp[i-1][jj][k][z]);
}
else {
if(k-1>=0)
dp[i][j][k-1][z]=min(dp[i][j][k-1][z],dp[i-1][jj][k][z]);
}
}
}
}
else{
rep(jj,0,1)
rep(k,0,s1)
rep(z,0,s2){
int d=a[i]%2;
if(d!=jj){
dp[i][d][k][z]=min(dp[i][d][k][z],dp[i-1][jj][k][z]+1);
}
else{
dp[i][d][k][z]=min(dp[i][d][k][z],dp[i-1][jj][k][z]);
}
}
}
}
printf("%d\n",min(dp[n][1][0][0],dp[n][0][0][0]));
}
D. Numbers on Tree
題意:給你一個樹,每個節點有個權值,然後每個節點有個c[i],代表着i這個子樹下有c[i]個點的值比i節點的權值小。
現問你能否構造每個節點的權值出來,能輸出這些權值。
做法:參考https://www.cnblogs.com/zzqc/p/12154912.html
大概就從子樹往上走,根據c[u]將每一個u,構造一個序列,如果u有多個子樹,那麼就將第二顆子樹的序列接在第一顆子樹的後面,爲什麼?
1,這時候很顯然的子樹之間是沒有關係的,可以給一棵子樹的值整體提高一個水平,使得得到的值也是相異的,最簡單的是加上上一棵子樹的最大值(而不一定是size,假如沒有進行算不併列的排名的話)。
子樹處理完,如何處理當前節點u呢?
子樹構造一個序列出來,當前節點u的c[u]就是這個序列的第幾位。
然後一直不知道這段怎麼去弄,發現n只有2000,那我暴力將所有的數往後移不就可以了。
用vector的insert函數就不用自己寫那麼多的代碼了。
#include<bits/stdc++.h>
using namespace std;
const int N=2e3+10;
vector<int>G[N];
int n,c[N],ans[N];
vector<int> dfs(int u,int fa)
{
vector<int>tmp;
for(int v:G[u]){
if(v==fa) continue;
vector<int>t=dfs(v,u);
tmp.insert(tmp.end(),t.begin(),t.end());
}
if(c[u]>tmp.size()){puts("NO");exit(0);}
tmp.insert(tmp.begin()+c[u],u);
return tmp;
}
int main()
{
scanf("%d",&n);
int root=1;
for(int i=1;i<=n;++i){
int fa;
scanf("%d%d",&fa,&c[i]);
if(fa!=0) G[fa].push_back(i),G[i].push_back(fa);
else root=i;
}
vector<int>res=dfs(root,0);
puts("YES");
for(int i=0;i<n;++i) ans[res[i]]=i+1;
for(int i=1;i<=n;++i) printf("%d ",ans[i]);
puts("");
return 0;
}