[考試反思]1104csp-s模擬測試100: 終結

這麼好的整數場,就終結了我連續莫名考好的記錄。數組

功德圓滿了。。。ide

仍是炸了啊。並且炸的還挺厲害(本身又上不去本身粘的榜單啦)測試

說實在的這場考試作的很是差勁。雖然說分數不算特別低可是表現是真的特別差。優化

T1看錯數據範圍,數組開小。spa

真的我之後只要不MLE仍是多開一點數組吧不會鍋的。code

並且好好看題好好看數據範圍!!!blog

T2亂搞+剪枝,數據水就過了。get

關鍵是T3。若是T3打個特別簡單的暴力拿40就滾的話就是並列rank1了(雖然說在文件評測下skyh多了5分會變成rank2)it

可是由於正解很好想,想到了正解就沒有打暴力。io

一個半小時,到死也沒調出來。

不要那麼自信啊餵你那麼菜老老實實打暴力啊先!!!

臨考前出這麼多問題,也不知道我是要怎樣。

改。改就是了。

 

T1:組合

根據題目暗示能夠抽象成圖論。

而後發現就是一個有/無向圖歐拉路板子。及時重置fir數組以及當前枚舉的邊i。(就是當前弧優化)

板子,看代碼就行了,這真的無法說。

注意數據範圍以及n和m的含義不要看反,不要想固然覺得nm同級。

 1 #include<cstdio>
 2 #define gg return puts("NO"),0
 3 int t,n,m,cnt=1,fir[2000005],l[2000005],to[2000005],in[2000005],out[2000005],deg[2000005];
 4 int al[2000005],S,E,el[2000005],ans[2000005],tp;
 5 void dfs(int p){
 6     al[p]=1;
 7     for(int i=fir[p];i;i=l[i])if(!al[to[i]])dfs(to[i]);
 8 }
 9 void DFS(int p){
10     for(int i=fir[p];i;)if(!el[i]){
11         el[i]=1;fir[p]=l[i];
12         if(t==1)el[i^1]=1;
13         DFS(to[i]);
14         ans[++tp]=i;i=fir[p];
15     }else fir[p]=i=l[i];
16 }
17 void link(int a,int b){l[++cnt]=fir[a];fir[a]=cnt;to[cnt]=b;in[b]++;out[a]++;}
18 int main(){
19     freopen("merge.in","r",stdin);
20     freopen("merge.out","w",stdout);
21     scanf("%d%d%d",&t,&n,&m);
22     if(t==1){
23         for(int i=1,x,y;i<=m;++i)scanf("%d%d",&x,&y),link(x,y),link(y,x);
24         for(int i=1;i<=n;++i)if(in[i]&1)
25             if(!S)S=i;else if(!E)E=i;else gg;
26         if(!S)for(int i=1;i<=n;++i)if(in[i])S=i;
27         dfs(S);
28         for(int i=1;i<=n;++i)if(!al[i]&&in[i])gg;
29         puts("YES");
30         DFS(S);
31         while(tp)printf("%d ",(ans[tp]>>1)*(ans[tp]&1?-1:1)),tp--;
32     }else{
33         for(int i=1,x,y;i<=m;++i)scanf("%d%d",&x,&y),link(x,y);
34         for(int i=1;i<=n;++i)
35             if(in[i]==out[i]+1){if(!E)E=i;else gg;}
36             else if(in[i]+1==out[i]){if(!S)S=i;else gg;}
37             else if(in[i]!=out[i])gg;
38         if(!S)for(int i=1;i<=n;++i)if(out[i])S=i;
39         dfs(S);
40         for(int i=1;i<=n;++i)if(!al[i]&&in[i])gg;
41         puts("YES");
42         DFS(S);
43         while(tp)printf("%d ",ans[tp]-1),tp--;
44     }
45 }
View Code

 

T2:統計

觀察大樣例,發現到了後來操做約等於沒操做,只有不多的狀況下會真正進行操做。

統計每一個數後面有幾個比它小的,若是沒有那麼就不操做。

這個統計能夠在求逆序對時求出。

 1 #include<cstdio>
 2 #include<algorithm>
 3 int a[200005],n,m,cnt[200005],t[200005],r[200005],rp[200005],tp;long long ans;
 4 void add(int p,int w=1){for(;p<=n;p+=p&-p)t[p]+=w;}
 5 int ask(int p,int a=0){for(;p;p^=p&-p)a+=t[p];return a;}
 6 void cal(int p){tp=0;
 7     for(int i=p;i<=n;++i)if(a[i]<=a[p])r[++tp]=a[i],rp[tp]=i;
 8     std::sort(r+1,r+1+tp);
 9     for(int i=1;i<=tp;++i)a[rp[i]]=r[i];
10     for(int i=1;i<=n;++i)t[i]=0;
11     for(int i=n;i>=p;--i)ans-=cnt[i],ans+=(cnt[i]=ask(a[i]-1)),add(a[i]);
12 }
13 int main(){
14     freopen("count.in","r",stdin);
15     freopen("count.out","w",stdout);
16     scanf("%d%d",&n,&m);
17     for(int i=1;i<=n;++i)scanf("%d",&a[i]);
18     for(int i=n;i;--i)ans+=(cnt[i]=ask(a[i]-1)),add(a[i]);
19     printf("%lld ",ans);
20     while(m--){
21         int x;scanf("%d",&x);
22         if(cnt[x])cal(x);
23         printf("%lld ",ans);
24     }
25 }
View Code

然而其實複雜度並很差,須要用線段樹或鏈表優化這個過程。

 

T3:點亮

首先聲明:題解傻逼了那個不是方案數那個是最優轉移值。。。

至今不知道考場上打的怎麼錯了。

猜想隨機數據生成的樹與徹底二叉樹相近,其實差很少,只不過2變成了e,log變成了ln。

考慮每個點對最終答案的貢獻。

枚舉u,再枚舉全部點v,獲得lca(u,v),根據u和lca(u,v)就能夠知道貢獻是a[u][v]仍是b[u][v]仍是0。

因此預處理以後其實貢獻就與v無關了,只與u和lca有關。

由於隨機樹的深度指望爲$ln \ n$(實際測試點裏稍大,爲14)

因此能夠狀壓祖先鏈上全部的點,1表示這個點的子樹裏點亮的點大於等於一半。

而後就能夠根據祖先鏈上的狀況判斷每一個點在如今狀況下的貢獻了。

而後狀態定義就是dp[i][j][k]表示以i爲根的子樹裏已經有j個點被點亮了,此時i的祖先鏈上的狀態爲k。

而後就能夠dp了。轉移就是經典的子樹歸併(因此可能須要滾動dp數組或者使用輔助數組,其實也能夠不用)。

形式也很簡單,什麼DP[p][S+s][j]=max(dp[p][S][j]+dp[son][s][k])什麼的。

狀態數挺多的,得拿vector來resize存。

沒什麼好說的。初值-inf。該預處理的預處理。

而後就是代碼細節問題。。。不是很好調,真的。。。

話說我感受我這個$O(n^2)$遞推求出全部點對的lca仍是挺帥的(僅適用於這種f[i]<i的)

 1 #include<cstdio>
 2 #include<vector>
 3 #include<algorithm>
 4 using namespace std;
 5 #define inf -66666666
 6 int max(int a,int b){return a>b?a:b;}
 7 int read(){
 8     register int nt=0,p=0;register char ch=getchar();
 9     while(ch<'0'||ch>'9')nt=ch=='-',ch=getchar();
10     while(ch>='0'&&ch<='9')p=(p<<3)+(p<<1)+ch-'0',ch=getchar();
11     return nt?-p:p;
12 }
13 int n,f[1005],a[1005][1005],b[1005][1005],lca[1005][1005],pre[2][1005][16];
14 int fir[1005],l[1005],to[1005],cnt,sz[1005],Dep[1005],DP[1005][32767];
15 vector<int>dp[1001][1001];
16 void link(int a,int b){l[++cnt]=fir[a];fir[a]=cnt;to[cnt]=b;}
17 void DFS(int p){
18     sz[p]=1;Dep[p]=Dep[f[p]]+1;
19     for(int i=fir[p];i;i=l[i])DFS(to[i]),sz[p]+=sz[to[i]];
20 }
21 void dfs(int p){int dep=Dep[p],alsz=1,S=(1<<dep)-1;
22     for(int i=0;i<=sz[p];++i)dp[p][i].resize(S+1),dp[p][i].resize(S+1);
23     for(int i=0;i<=sz[p];++i)for(int j=0;j<1<<dep;++j)dp[p][i][j]=dp[p][i][j]=inf;
24     for(int j=0;j<1<<dep;++j){
25         dp[p][0][j]=dp[p][1][j]=0;
26         for(int i=1;i<=15;++i)if(!(j&1<<i-1))dp[p][0][j]+=pre[0][p][i];else dp[p][1][j]+=pre[1][p][i];
27     }
28     for(int i=fir[p];i;i=l[i]){int t=to[i];
29         dfs(t);
30         for(int i=0;i<=alsz+sz[t];++i)for(int j=0;j<1<<dep;++j)DP[i][j]=inf;
31         for(int j=0;j<=sz[t];++j)for(int k=0;k<1<<dep;++k)for(int x=0;x<=alsz;++x)
32             DP[x+j][k]=max(DP[x+j][k],dp[p][x][k]+max(dp[t][j][k],dp[t][j][k+S+1]));
33         for(int i=0;i<=alsz+sz[t];++i)for(int j=0;j<1<<dep;++j)dp[p][i][j]=DP[i][j];
34         alsz+=sz[t];
35     }
36     for(int i=0;i<=sz[p];++i)for(int j=0;j<1<<dep;++j)
37         if(i<sz[p]-i&&j&1<<dep-1)dp[p][i][j]=inf;
38         else if(i>=sz[p]-i&&!(j&1<<dep-1))dp[p][i][j]=inf;
39 }
40 main(){
41     freopen("light.in","r",stdin);
42     freopen("light.out","w",stdout);
43     n=read();
44     for(int i=2;i<=n;++i)f[i]=read(),link(f[i],i);
45     for(int i=1;i<=n;++i){
46         for(int j=1;j<i;++j)a[i][j]=read(),b[i][j]=read();
47         for(int j=i+1;j<=n;++j)a[i][j]=read(),b[i][j]=read();
48     }
49     for(int i=1;i<=n;++i)lca[i][i]=i;
50     for(int i=1;i<=n;++i)for(int j=1;j<i;++j)lca[i][j]=lca[j][i]=lca[f[i]][j];
51     for(int i=1;i<=n;++i)for(int j=i+1;j<=n;++j)lca[i][j]=lca[j][i];
52     DFS(1);
53     for(int i=1;i<=n;++i)for(int j=1;j<=n;++j)lca[i][j]=Dep[lca[i][j]];
54     for(int i=1;i<=n;++i)for(int j=1;j<=n;++j)
55         pre[0][i][lca[i][j]]+=a[i][j],pre[1][i][lca[i][j]]+=b[i][j];
56     dfs(1);
57     int ans=inf;
58     for(int i=0;i<=sz[1];++i)ans=max(ans,max(dp[1][i][0],dp[1][i][1]));
59     printf("%d\n",ans);
60 }
View Code

注意那個pre數組的預處理,這個不能在裏面枚舉祖先狀態時再枚舉每個點暴力求,會退化成$O(n^3)$

 1 #include<cstdio>
 2 #include<vector>
 3 #include<algorithm>
 4 using namespace std;
 5 #define inf -66666666
 6 int max(int a,int b){return a>b?a:b;}
 7 int read(){
 8     register int nt=0,p=0;register char ch=getchar();
 9     while(ch<'0'||ch>'9')nt=ch=='-',ch=getchar();
10     while(ch>='0'&&ch<='9')p=(p<<3)+(p<<1)+ch-'0',ch=getchar();
11     return nt?-p:p;
12 }
13 int n,f[1005],a[1005][1005],b[1005][1005],lca[1005][1005];
14 int fir[1005],l[1005],to[1005],cnt,sz[1005],Dep[1005],DP[1005][32767];
15 vector<int>dp[1005][1005];
16 void link(int a,int b){l[++cnt]=fir[a];fir[a]=cnt;to[cnt]=b;}
17 void DFS(int p){
18     sz[p]=1;Dep[p]=Dep[f[p]]+1;
19     for(int i=fir[p];i;i=l[i])DFS(to[i]),sz[p]+=sz[to[i]];
20 }
21 void dfs(int p){int dep=Dep[p],alsz=1,S=(1<<dep)-1;
22     for(int i=0;i<=sz[p];++i)dp[p][i].resize(S+1),dp[p][i].resize(S+1);
23     for(int i=0;i<=sz[p];++i)for(int j=0;j<1<<dep;++j)dp[p][i][j]=dp[p][i][j]=inf;
24     for(int j=0;j<1<<dep;++j){
25         dp[p][0][j]=dp[p][1][j]=0;
26         for(int i=1;i<=n;++i)if(!(j&1<<lca[p][i]-1))dp[p][0][j]+=a[p][i];
27         for(int i=1;i<=n;++i)if(j&1<<lca[p][i]-1)dp[p][1][j]+=b[p][i];
28     }
29     for(int i=fir[p];i;i=l[i]){int t=to[i];
30         dfs(t);
31         for(int i=0;i<=alsz+sz[t];++i)for(int j=0;j<1<<dep;++j)DP[i][j]=inf;
32         for(int x=0;x<=alsz;++x)for(int j=0;j<=sz[t];++j)for(int k=0;k<1<<dep;++k)
33             DP[x+j][k]=max(DP[x+j][k],dp[p][x][k]+max(dp[t][j][k],dp[t][j][k+S+1]));
34             for(int i=0;i<=alsz+sz[t];++i)for(int j=0;j<1<<dep;++j)dp[p][i][j]=DP[i][j];
35         
36         alsz+=sz[t];
37     }
38     for(int i=0;i<=sz[p];++i)for(int j=0;j<1<<dep;++j)
39         if(i<sz[p]-i&&j&1<<dep-1)dp[p][i][j]=inf;
40         else if(i>=sz[p]-i&&!(j&1<<dep-1))dp[p][i][j]=inf;
41 }
42 int main(){
43     freopen("light.in","r",stdin);
44     freopen("light.out","w",stdout);
45     n=read();
46     for(int i=2;i<=n;++i)f[i]=read(),link(f[i],i);
47     for(int i=1;i<=n;++i){
48         for(int j=1;j<i;++j)a[i][j]=read(),b[i][j]=read();
49         for(int j=i+1;j<=n;++j)a[i][j]=read(),b[i][j]=read();
50     }
51     for(int i=1;i<=n;++i)lca[i][i]=i;
52     for(int i=1;i<=n;++i)for(int j=1;j<i;++j)lca[i][j]=lca[j][i]=lca[f[i]][j];
53     for(int i=1;i<=n;++i)for(int j=i+1;j<=n;++j)lca[i][j]=lca[j][i];
54     DFS(1);
55     for(int i=1;i<=n;++i)for(int j=1;j<=n;++j)lca[i][j]=Dep[lca[i][j]];
56     dfs(1);
57     int ans=inf;
58     for(int i=0;i<=sz[1];++i)ans=max(ans,max(dp[1][i][0],dp[1][i][1]));
59     printf("%d\n",ans);
60 }
就像這樣

%%%mikufun爲何調代碼那麼快啊我調了半場考試加一個晚上才弄出來他半個晚上就過樣例直接秒切了

我好菜啊QAQ

相關文章
相關標籤/搜索