NOIp2018集训test-9-23

这个NOI模拟题怕是比你们的NOIp模拟题要简单哦。。

友好的生物

应该是一道简单题,但是机房只有辉神一个人想到正解似乎。

被我kd-tree水过去了(这不是kd-tree的裸题吗???(不是))

  1 //Achen
  2 #include<bits/stdc++.h>
  3 #define For(i,a,b) for(int i=(a);i<=(b);i++)
  4 #define Rep(i,a,b) for(int i=(a);i>=(b);i--)
  5 #define Formylove return 0
  6 #define inf 1e18
  7 const int N=100007;
  8 using namespace std;
  9 typedef long long LL;
 10 typedef double db;
 11 int n,K,D;
 12 LL C[10],ans;
 13 
 14 template<typename T>void read(T &x) {
 15     T f=1; x=0; char ch=getchar();
 16     while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
 17     if(ch=='-') f=-1,ch=getchar();
 18     for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
 19 }
 20 
 21 struct node {
 22     int d[5];
 23     friend bool operator <(const node&A,const node&B) {
 24         return A.d[D]<B.d[D];
 25     }
 26 }p[N],q[N],T;
 27 
 28 void get_min(int &x,int y) { if(x>y) x=y; }
 29 void get_max(int &x,int y) { if(x<y) x=y; }
 30 
 31 int rt,ch[N][2],dt[N][5][2];
 32 #define lc ch[x][0]
 33 #define rc ch[x][1]
 34 #define mid ((l+r)>>1)
 35 void update(int x,int l,int r) {
 36     For(i,0,K-1) dt[x][i][0]=dt[x][i][1]=p[x].d[i];
 37     if(lc) For(i,0,K-1) {
 38         get_min(dt[x][i][0],dt[lc][i][0]);
 39         get_max(dt[x][i][1],dt[lc][i][1]);
 40     }
 41     if(rc) For(i,0,K-1) {
 42         get_min(dt[x][i][0],dt[rc][i][0]);
 43         get_max(dt[x][i][1],dt[rc][i][1]);
 44     }
 45 }
 46 
 47 int build(int l,int r,int k) {
 48     if(l>r) return 0;
 49     D=k;
 50     sort(p+l,p+r+1);
 51     int x=((l+r)>>1);
 52     lc=build(l,x-1,(k+1)%K);
 53     rc=build(x+1,r,(k+1)%K);
 54     update(x,l,r);
 55     return x;
 56 }
 57 
 58 void get_ans(int x) {
 59     LL rs=0;
 60     For(i,0,K-2) rs+=abs(p[x].d[i]-T.d[i])*C[i];
 61     rs-=abs(p[x].d[K-1]-T.d[K-1])*C[K-1];
 62     ans=max(ans,rs);
 63 }
 64 
 65 LL guess_min(int x) {
 66     LL rs=0;
 67     For(i,0,K-2) {
 68         if(dt[x][i][0]<=T.d[i]&&dt[x][i][1]>=T.d[i]) continue;
 69         if(T.d[i]<dt[x][i][0]) rs+=(dt[x][i][0]-T.d[i])*C[i];
 70         else rs+=(T.d[i]-dt[x][i][1])*C[i];
 71     }
 72     rs-=max(abs(T.d[K-1]-dt[x][K-1][0]),abs(T.d[K-1]-dt[x][K-1][1]))*C[K-1];
 73     return rs;
 74 }
 75 
 76 LL guess_max(int x) {
 77     if(!x) return -inf;
 78     LL rs=0;
 79     For(i,0,K-2) {
 80         rs+=max(abs(T.d[i]-dt[x][i][0]),abs(T.d[i]-dt[x][i][1]))*C[i];
 81     }
 82     if(T.d[K-1]<dt[x][K-1][0]) rs-=(dt[x][K-1][0]-T.d[K-1])*C[K-1];
 83     else if(T.d[K-1]>dt[x][K-1][1]) rs-=(T.d[K-1]-dt[x][K-1][1])*C[K-1];
 84     return rs;
 85 }
 86 
 87 void qry(int x,int l,int r,int k) {
 88     if(!x||l>r) return ;
 89     get_ans(x);
 90     LL lg=guess_max(lc);
 91     LL rg=guess_max(rc);
 92     if(lg<=ans&&rg<=ans) return ;
 93     if(lg>=rg) {
 94         qry(lc,l,mid-1,(k+1)%K);
 95         if(rg>ans) qry(rc,mid+1,r,(k+1)%K);
 96     }
 97     else {
 98         qry(rc,mid+1,r,(k+1)%K);
 99         if(lg>ans) qry(lc,l,mid-1,(k+1)%K);
100     }
101 }
102 
103 #define ANS
104 int main() {
105 #ifdef ANS
106     freopen("species.in","r",stdin);
107     freopen("species.out","w",stdout);
108 #endif
109     read(n); read(K);
110     For(i,0,K-1) read(C[i]);
111     For(i,1,n) {
112         For(j,0,K-1) read(p[i].d[j]);
113         q[i]=p[i];
114     }
115     ans=-inf;
116     rt=build(1,n,0);
117     For(i,1,n) {
118         T=q[i];
119         qry(rt,1,n,0);
120     }
121     printf("%lld\n",ans);
122     //cerr<<clock()<<endl;
123     Formylove;
124 }
kd-tree

正解:

这个题其实是三道题中最简单的一道。先来看这个问题的一个简化版,假设所有的属性都是差值越大越友好的话:

 

那么,这个题目会变得简单很多,我们依次枚举在最有情况下,每一种属性值是编号小的动物大,还是编号大的动物大。假设,对于第i种属性,编号小的动物大这种情况用t[i]=-1表示,编号大的动物属性值大这种情况用t[i]=1表示。那么,动物i和动物j的属性值

 

并且,我们总有一个时刻可以枚举对每一种属性的情况,使等号成立。所以,我们可以通过寻找右侧式子的最大值来确定左侧式子的最大值。

回到本题,题目中的最后一个属性和前面的是反过来的,即差值越小越友好,在这种情况下,我们可以先将动物们按照最后一个属性值来排序,之后按照上面给出的做法实现就可以了。

正解当然优美很多了

 1 //Achen
 2 #include<bits/stdc++.h>
 3 #define For(i,a,b) for(int i=(a);i<=(b);i++)
 4 #define Rep(i,a,b) for(int i=(a);i>=(b);i--)
 5 #define Formylove return 0
 6 #define inf 1e18
 7 const int N=100007;
 8 using namespace std;
 9 typedef long long LL;
10 typedef double db;
11 int n,K,D;
12 LL C[10],ans;
13 
14 template<typename T>void read(T &x) {
15     T f=1; x=0; char ch=getchar();
16     while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
17     if(ch=='-') f=-1,ch=getchar();
18     for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
19 }
20 
21 struct node {
22     int d[5];
23     friend bool operator <(const node&A,const node&B) {
24         return A.d[K-1]>B.d[K-1];
25     }
26 }p[N];
27 
28 #define ANS
29 int main() {
30 #ifdef ANS
31     freopen("species.in","r",stdin);
32     freopen("species.out","w",stdout);
33 #endif
34     read(n); read(K);
35     For(i,0,K-1) read(C[i]);
36     For(i,1,n) {
37         For(j,0,K-1) read(p[i].d[j]);
38     }
39     sort(p+1,p+n+1);
40     LL pr=inf;
41     ans=-inf;
42     int up=(1<<K-1)-1;
43     For(t,0,up) {
44         pr=inf;
45         For(i,1,n) {
46             LL tp=0;
47             For(d,1,K-1) if(t&(1<<d-1)) tp-=C[d-1]*p[i].d[d-1];
48             else tp+=C[d-1]*p[i].d[d-1]; 
49             ans=max(ans,tp+C[K-1]*p[i].d[K-1]-pr);
50             pr=min(pr,tp+C[K-1]*p[i].d[K-1]);
51         }
52     }
53     printf("%lld\n",ans);
54     //cerr<<clock()<<endl;
55     Formylove;
56 }
View Code

 

 

基因重组

这是个真水题,n^2dp随便怎么做,我做的时候脑子有点抽写得有点奇怪,还用了short卡空间。。但是这个dp随便怎么写都能过吧。

 1 //Achen
 2 #include<bits/stdc++.h>
 3 #define For(i,a,b) for(int i=(a);i<=(b);i++)
 4 #define Rep(i,a,b) for(int i=(a);i>=(b);i--)
 5 #define Formylove return 0
 6 const int N=5007;
 7 using namespace std;
 8 typedef long long LL;
 9 typedef double db;
10 int n,m,up=24400,c1,c2,c3;
11 short s1[N][N],f[N][N],mi[N],ans;
12 LL x;
13 char a[N],b[N],a2[N];
14 
15 template<typename T>void read(T &x) {
16     T f=1; x=0; char ch=getchar();
17     while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
18     if(ch=='-') f=-1,ch=getchar();
19     for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
20 }
21 
22 void get_min(short &x,int y) { if(x>y) x=y; }
23 
24 #define ANS
25 int main() {
26 #ifdef ANS
27     freopen("DNA.in","r",stdin);
28     freopen("DNA.out","w",stdout);
29 #endif
30     read(x); if(x>up) c1=up+1; else c1=x;
31     read(x); if(x>up) c2=up+1; else c2=x;
32     read(x); if(x>up) c3=up+1; else c3=x;
33     scanf("%s",a); n=strlen(a);
34     For(i,0,n-1) {
35         if(a[i]=='A') a2[i]='T';
36         else if(a[i]=='T') a2[i]='A';
37         else if(a[i]=='C') a2[i]='G';
38         else if(a[i]=='G') a2[i]='C';
39     }
40     scanf("%s",b); m=strlen(b);
41     Rep(i,n,1) Rep(j,m,1) {
42         if(a[i-1]==b[j-1]) s1[i][j]=s1[i+1][j+1]+1;
43         else s1[i][j]=0;
44         if(a2[i-1]==b[j-1]) f[i][j]=f[i+1][j+1]+1;
45         else f[i][j]=0;
46     }
47     For(i,1,n) For(j,1,m) s1[i][j]=max(s1[i][j],f[i][j]);
48     memset(f,127,sizeof(f));
49     memset(mi,127,sizeof(mi));
50     mi[0]=0;
51     f[0][0]=0; ans=up;
52     For(i,0,n) {
53         For(j,0,m) {
54             get_min(f[i][j],(int)mi[j]+c2);
55             mi[j]=min(mi[j],f[i][j]);
56             int t=s1[i+1][j+1];
57             get_min(f[i+t][j+t],(int)f[i][j]+c1);
58             if(j==m) get_min(ans,(int)f[i][j]);
59             else get_min(f[i][j+1],(int)f[i][j]+c3);
60         }
61     }
62     printf("%d\n",(int)ans);
63     //cerr<<clock()<<endl;
64     Formylove;
65 }
View Code

 

危险的迷宫

好多人切这题啊。。。全机房就我一个人不知道这题是费用流???

这不是一道插头dp的裸题吗????

人类,你们对插头dp一无所知!

作死写了百行转移,结果大样例都没过,交上去还水过了50pt.

然后de了一晚上。。。

一个是有个地方n和m写反了,另外两个是两段轮廓线上一个是1一个是2的时候,如果这个格子本身是1或者2那么是不合法的,不能直接合并清0了!两句话价值一晚上+50pt。

  1 //Achen
  2 #include<bits/stdc++.h>
  3 #define For(i,a,b) for(int i=(a);i<=(b);i++)
  4 #define Rep(i,a,b) for(int i=(a);i>=(b);i--)
  5 #define Formylove return 0
  6 const int N=177148;
  7 using namespace std;
  8 typedef long long LL;
  9 typedef double db;
 10 int n,m,K,C,f[12][12][N],inf,pr[30];
 11 int a[15][15],is[15][15],rr[15][15],dn[15][15];
 12 
 13 template<typename T>void read(T &x) {
 14     T f=1; x=0; char ch=getchar();
 15     while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
 16     if(ch=='-') f=-1,ch=getchar();
 17     for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
 18 }
 19 
 20 void GM(int &x,int y) { if(x>y) x=y; }
 21 int get(int s,int k) {
 22     return s/pr[k-1]%3;
 23 }
 24 
 25 #define ANS
 26 int main() {
 27 #ifdef ANS
 28     freopen("maze.in","r",stdin);
 29     freopen("maze.out","w",stdout);
 30 #endif
 31     read(n); read(m);
 32     For(i,1,n) For(j,1,m) read(a[i][j]);
 33     read(K);
 34     For(i,1,K) {
 35         int x1,y1,x2,y2;
 36         read(x1); read(y1);
 37         read(x2); read(y2);
 38         if(x1>x2) swap(x1,x2),swap(y1,y2);
 39         if(x1<x2) dn[x1][y1]=1;
 40         else {
 41             if(y1>y2) swap(y1,y2);
 42             rr[x1][y1]=1;
 43         } 
 44     }
 45     read(C);
 46     For(i,1,C) {
 47         int x,y;
 48         read(x); read(y);
 49         is[x][y]=1;
 50     }
 51     For(i,1,C) {
 52         int x,y;
 53         read(x); read(y);
 54         is[x][y]=2;
 55     }
 56     /*For(i,1,n) {
 57         For(j,1,m) {
 58             printf("%d ",rr[i][j]);
 59         } puts("");
 60     }
 61     For(i,1,n) {
 62         For(j,1,m) {
 63             printf("%d ",dn[i][j]);
 64         } puts("");
 65     }
 66     For(i,1,n) {
 67         For(j,1,m) {
 68             if(is[i][j]) printf("%d(%d)",a[i][j],is[i][j]);
 69             else printf("%d",a[i][j]);
 70     }*/
 71     pr[0]=1;
 72     For(i,1,20) pr[i]=pr[i-1]*3;
 73     memset(f,127/3,sizeof(f));
 74     inf=f[0][0][0];
 75     f[1][1][0]=0;
 76     int up=pr[m+1]-1;
 77     For(i,1,n) {
 78         For(j,1,m) {
 79             For(s,0,up) if(f[i][j][s]!=inf) {
 80                 int prs=s;
 81                 if(j==1) s*=3;
 82                 int f1=get(s,j),f2=get(s,j+1);
 83                 int ii,jj;
 84                 if(j==m) ii=i+1,jj=1;
 85                 else ii=i,jj=j+1;
 86                 if(!f1) {
 87                     if(!f2) {
 88                         if(is[i][j]) {
 89                             if(rr[i][j]) GM(f[ii][jj][s+is[i][j]*pr[j]],f[i][j][prs]+a[i][j]);
 90                             if(dn[i][j]) GM(f[ii][jj][s+is[i][j]*pr[j-1]],f[i][j][prs]+a[i][j]);
 91                         }
 92                         else {
 93                             GM(f[ii][jj][s],f[i][j][prs]);
 94                             if(rr[i][j]&&dn[i][j]) {
 95                                 GM(f[ii][jj][s+pr[j-1]+2*pr[j]],f[i][j][prs]+a[i][j]);
 96                                 GM(f[ii][jj][s+2*pr[j-1]+pr[j]],f[i][j][prs]+a[i][j]);
 97                             }
 98                         }
 99                     }
100                     if(f2==1) {
101                         if(is[i][j]==2) 
102                             GM(f[ii][jj][s-pr[j]],f[i][j][prs]+a[i][j]);
103                         else if(!is[i][j]) {
104                             if(rr[i][j]) GM(f[ii][jj][s],f[i][j][prs]+a[i][j]);
105                             if(dn[i][j]) GM(f[ii][jj][s+pr[j-1]-pr[j]],f[i][j][prs]+a[i][j]);
106                         }
107                     }
108                     if(f2==2) {
109                         if(is[i][j]==1) 
110                             GM(f[ii][jj][s-2*pr[j]],f[i][j][prs]+a[i][j]);
111                         else if(!is[i][j]) {
112                             if(rr[i][j]) GM(f[ii][jj][s],f[i][j][prs]+a[i][j]);
113                             if(dn[i][j]) GM(f[ii][jj][s+2*pr[j-1]-2*pr[j]],f[i][j][prs]+a[i][j]);
114                         }
115                     }
116                 }
117                 else if(f1==1) {
118                     if(!f2) {
119                         if(is[i][j]==2) 
120                             GM(f[ii][jj][s-pr[j-1]],f[i][j][prs]+a[i][j]);
121                         else if(!is[i][j]) {
122                             if(rr[i][j]) GM(f[ii][jj][s-pr[j-1]+pr[j]],f[i][j][prs]+a[i][j]);
123                             if(dn[i][j]) GM(f[ii][jj][s],f[i][j][prs]+a[i][j]);
124                         }
125                     }
126                     if(f2==1) ;
127                     if(f2==2&&!is[i][j]) 
128                         GM(f[ii][jj][s-pr[j-1]-2*pr[j]],f[i][j][prs]+a[i][j]);
129                 }
130                 else if(f1==2) {
131                     if(!f2) {
132                         if(is[i][j]==1) 
133                             GM(f[ii][jj][s-2*pr[j-1]],f[i][j][s]+a[i][j]);
134                         else if(!is[i][j]) {
135                             if(rr[i][j]) GM(f[ii][jj][s-2*pr[j-1]+2*pr[j]],f[i][j][s]+a[i][j]);
136                             if(dn[i][j]) GM(f[ii][jj][s],f[i][j][s]+a[i][j]);
137                         }
138                     }
139                     if(f2==1&&!is[i][j]) 
140                         GM(f[ii][jj][s-2*pr[j-1]-pr[j]],f[i][j][s]+a[i][j]);
141                     if(f2==2) ;
142                 }
143                 s=prs;
144                 if(f[3][4][0]!=inf) {
145                     int debug=1;
146                 }
147             }
148         }        
149     }
150     if(f[n+1][1][0]==inf) puts("-1");
151     else printf("%d\n",f[n+1][1][0]);
152     //cerr<<clock()<<endl;
153     Formylove;
154 }
View Code

 

posted @ 2018-10-05 18:56  啊宸  阅读(211)  评论(1编辑  收藏  举报