码迷,mamicode.com
首页 > 其他好文 > 详细

是时候开刷NOI了

时间:2015-06-21 21:01:56      阅读:98      评论:0      收藏:0      [点我收藏+]

标签:

整天挨着毛爷爷,压力好大。。

看毛爷爷即将炖完NOI,我的确也该刷了

原则是从头到尾自己想(虽然看了一次题解),可以不A掉。

 

NOI2009

day1:

T1

题目略神,我还是不讲了。。。(就这题我WA了好多遍 TAT)

技术分享
 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 #include <bitset>
 5 #include <vector>
 6  
 7 #define N 20010
 8  
 9 using namespace std;
10  
11 struct edge{
12     int x,to;
13 }E[N<<2];
14  
15 int n,a[N],pre[N],totE,g[N];
16 bitset<N> v;
17 vector<int> G[N];
18  
19 #define p G[x][i]
20  
21 void ade(int x,int y){
22     G[x].push_back(y);
23 }
24  
25 int find(int x){
26     v[x]=1;
27     int len=G[x].size();
28     for(int i=0;i<len;i++)
29         if(!v[p]){
30             v[p]=1;
31             if(!pre[p]||find(pre[p])){
32                 pre[p]=x; pre[x]=p;
33                 return 1;
34             }
35         }
36     return 0;
37 }
38  
39 int main(){
40     freopen("transform.in","r",stdin);
41     freopen("transform.out","w",stdout);
42     scanf("%d",&n);
43     for(int i=1;i<=n;i++){
44         scanf("%d",&a[i]);
45     }
46     for(int i=1;i<=n;i++){
47         if(i-a[i]>=1) G[i].push_back(n+i-a[i]);
48         else G[i].push_back(n+i-a[i]+n);
49         if(i+a[i]<=n) G[i].push_back(n+i+a[i]);
50         else G[i].push_back(i+a[i]);
51     }
52     for(int i=1;i<=n;i++) sort(G[i].begin(),G[i].end());
53     int ans=0;
54     for(int i=n;i>=1;i--){
55         v.reset();
56         if(find(i)) ans++;
57     }
58     if(ans!=n){
59         puts("No Answer");
60     }
61     else{
62         for(int i=1;i<n;i++) printf("%d ",pre[i]-n-1);
63         printf("%d\n",pre[n]-n-1);
64     }
65     return 0;
66 }
View Code

 

 

T2

脑补一下,这个应该是一个单峰函数,果断三分。

爆long long QAQ,这要是NOI我就被坑死啦,long double过。

技术分享
 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4  
 5 #define LL long long
 6 #define N 200010
 7 #define LD long double
 8  
 9 using namespace std;
10  
11 int n,P;
12 int len[N],pre[N];
13 LL L;
14 LD f[N];
15 char S[N][52];
16  
17 LD qpow(LD x,LL n){
18     LD ans=1;
19     for(;n;n>>=1,x*=x)
20         if(n&1) ans*=x;
21     return ans;
22 }
23  
24 LD Abs(LL x){
25     if(x<0) return -(LD)x;
26     return (LD)x;
27 }
28  
29 LD F(int i,int j){
30     return f[j]+
31         qpow(Abs(L-(len[i]-len[j]+i-j-1LL)),P); 
32 }
33  
34 int find(int i){
35     int l=0,r=i-1,m1,m2;
36     while(r-l>10){
37         m1=l+(r-l)/3;
38         m2=r-(r-l)/3;
39         if(F(i,m1)<F(i,m2)) r=m2;
40         else l=m1;
41     }
42     LD ans=F(i,0);
43     int pos=0;
44     for(int t=l;t<=r;t++)
45         if(F(i,t)<ans){
46             ans=F(i,t);
47             pos=t;
48         }
49     return pos;
50 }
51  
52 void print(int t){
53     if(pre[t]) print(pre[t]);
54     for(int i=pre[t]+1;i<t;i++){
55         printf("%s ",S[i]);
56     }
57     printf("%s\n",S[t]);
58 }
59  
60 int main(){
61     freopen("noi09_poet.in","r",stdin);
62     freopen("noi09_poet.out","w",stdout);
63     int T;
64     scanf("%d",&T);
65     while(T--){
66         scanf("%d %lld %d",&n,&L,&P);
67         for(int i=1;i<=n;i++){
68             scanf("%s",S[i]);
69             len[i]=strlen(S[i]);
70         }
71         for(int i=2;i<=n;i++) len[i]+=len[i-1];
72         memset(f,127,sizeof(f));
73         f[0]=0;
74         for(int i=1;i<=n;i++){
75             int j=find(i);
76             f[i]=f[j]+qpow(Abs(L-(len[i]-len[j]+i-j-1LL)),P);
77             pre[i]=j;
78         }
79         if(f[n]>1e18){
80             puts("Too hard to arrange");
81         }
82         else{
83             printf("%lld\n",(LL)(f[n]));
84             print(n);
85         }
86         puts("--------------------");
87     }
88     return 0;
89 }
View Code

 

T3

QAQ好难,膜毛爷爷。

首先所谓 (频度 x 深度) 我们可以每过一层就加上当前的频度得到答案。

利用先序遍历的特殊性质(TAT 其实想到这个就差不多了),考虑dp。

f[i][j][k] 表示先序遍历从 i 到 j 作为一个子树(可能多个),而且满足所有权值小于等于k的最小花费。

转移分两种情况,修改当前root权值,修改子树权值。

$O(n^4)$ dp即可。

技术分享
 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 #include <iostream>
 5  
 6 #define N 80
 7 #define LL long long
 8 #define INF 0x7f7f7f7f7f7f7f7fLL
 9 #define debug(x) cout<<#x<<" = "<<x<<endl;
10  
11 using namespace std;
12  
13 int n,tot0;
14 int a[N],b[N],c[N],X[N];
15 LL K;
16 LL dp[N][N][N];
17 LL s[N][N];
18  
19 /*
20 O(n^5)
21  
22 f[i][j][k]
23 i到j之间的所有数值大于k,
24 消灭当前点    f[i][j][k] = min{ f[i][p-1][k] + f[p+1][j][k] + s[i][j] + K }
25 不消灭当前点    f[i][j][k] = min{ f[i][p-1][b[p]] + f[p+1][j][b[p]] + s[i][j] }
26 */
27  
28 LL F(int i,int j,int k){
29     if(i>j) return 0;
30 //    printf("%d %d %d\n",i,j,k);
31     if(dp[i][j][k]) return dp[i][j][k];
32     if(i==j) return dp[i][j][k]=b[i]<k ?K+c[i]:c[i];
33     dp[i][j][k]=INF;
34     for(int p=i;p<=j;p++){    //改当前点权 
35         dp[i][j][k]=min(dp[i][j][k],F(i,p-1,k) + F(p+1,j,k) + s[i][j] + K);
36         if(b[p]>=k){    //不改当前点权
37             dp[i][j][k]=min(dp[i][j][k],F(i,p-1,b[p]) + F(p+1,j,b[p]) + s[i][j]);
38         }
39     }
40     return dp[i][j][k];
41 }
42  
43 void init(){
44     for(int i=1;i<n;i++)
45         for(int j=i+1;j<=n;j++)
46             if(a[i]>a[j]){
47                 swap(a[i],a[j]);
48                 swap(b[i],b[j]);
49                 swap(c[i],c[j]);
50             }
51     sort(X+1,X+n+1);
52     tot0=1;
53     for(int i=2;i<=n;i++)
54         if(X[i]!=X[i-1]) X[++tot0]=X[i];
55     for(int i=1;i<=n;i++)
56         b[i]=lower_bound(X+1,X+tot0+1,b[i])-X;
57     for(int i=1;i<=n;i++){
58         s[i][i]=c[i];
59         for(int j=i+1;j<=n;j++)
60             s[i][j]=s[i][j-1]+c[j];
61     }
62 }
63  
64 int main(){
65     freopen("treapmod.in","r",stdin);
66     freopen("treapmod.out","w",stdout);
67     scanf("%d%d",&n,&K);
68     for(int i=1;i<=n;i++) scanf("%d",&a[i]);
69     for(int i=1;i<=n;i++){
70         scanf("%d",&b[i]);
71         X[i]=b[i];
72     }
73     for(int i=1;i<=n;i++) scanf("%d",&c[i]);
74     init();
75     LL ans=INF;
76     for(int i=1;i<=n;i++){
77         ans=min(ans,F(1,n,b[i]));
78     }
79     cout<<ans<<endl;
80     return 0;
81 }
View Code

 

day2

T1:

裸网络流,注意要拓扑一下,还要判环,环内的植物不能碰。

 

T2:

又是一道$dp$,思路很神(TAT 实在不会,看了题解)。

就是将 平方和 转化为结果相同的方案对数(自己也算)

然后裸dp上。

技术分享
 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4  
 5 #define N 510
 6 #define mod 1024523
 7  
 8 using namespace std;
 9  
10 /*
11 f[i][j][k]表示上面取了上i下j,上k。 
12 */
13  
14 char S1[N],S2[N];
15 int f[N][N][N],n,m;
16  
17 int add(int a,int b){
18     if(a+b<mod) return a+b;
19     return a+b-mod;
20 }
21  
22 int main(){
23     freopen("ballb.in","r",stdin);
24     freopen("ballb.out","w",stdout);
25     scanf("%d%d%s%s",&n,&m,S1,S2);
26     reverse(S1,S1+n);
27     reverse(S2,S2+m);
28     f[0][0][0]=1;
29     for(int i=0;i<=n;i++){
30         for(int j=0;j<=m;j++){
31             for(int k=0;k<=n;k++){
32                 if(!f[i][j][k]) continue;
33                 int l = i+j-k;
34                 if(l<0) break;
35                 //printf("f[%d][%d][%d] = %d\n",i,j,k,f[i][j][k]);
36                 if(i<n && k<n && S1[i]==S1[k]){
37                     f[i+1][j][k+1] = add(f[i+1][j][k+1],f[i][j][k]);
38                 }
39                 if(i<n && l<m && S1[i]==S2[l]){
40                     f[i+1][j][k] = add(f[i+1][j][k],f[i][j][k]);
41                 }
42                 if(j<m && k<n && S2[j]==S1[k]){
43                     f[i][j+1][k+1] = add(f[i][j+1][k+1],f[i][j][k]); 
44                 }
45                 if(j<m && l<m && S2[j]==S2[l]){
46                     f[i][j+1][k] = add(f[i][j+1][k],f[i][j][k]);
47                 }
48             }
49         }
50     }
51     printf("%d\n",f[n][m][n]);
52     return 0;
53 }
View Code

 

T3:

很好的提交答案题。

做好了70分吧。

是时候开刷NOI了

标签:

原文地址:http://www.cnblogs.com/lawyer/p/4592388.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!