2017/7/27 考试吐槽

2017 07 27 分数:152

一句话:我菜爆了……

A、玛雅游戏

吐槽时间:这是要每天一道爆搜的节奏吗……太长不打

题解:爆搜!爆搜!爆搜!没啥说的!

(话说回来这函数真恶心……又长又乱……大不了NOIP爆搜100分不要了

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<vector>
  6 #define R register
  7 using namespace std;
  8 int map[6][8],n,num[6],backup[6][6][8];
  9 vector<int>row,col,dire;
 10 inline void Fall()
 11 {
 12     for(R int i=1;i<=5;++i)
 13     {
 14         int val=0;
 15         for(R int j=1;j<=7;++j)
 16             if(map[i][j]&&val)swap(map[i][j-val],map[i][j]);
 17             else if(!map[i][j])val++;
 18     }
 19 }
 20 bool t,clear[6][8];
 21 inline void Wipe()
 22 {
 23     memset(clear,0,sizeof(clear));
 24     for(R int i=1;i<=5;++i)
 25         for(R int j=1;j<=7;++j)
 26             if(map[i][j])
 27             {
 28                 int cnt=0;
 29                 for(R int k=i;k<=5&&map[k][j]==map[i][j];++k)cnt++;
 30                 if(cnt>=3)
 31                 {
 32                     t=1;
 33                     for(R int k=i;k<i+cnt;++ k)clear[k][j]=1;
 34                 }
 35                 cnt=0;
 36                 for(R int k=j;k<=7&&map[i][k]==map[i][j];++k)cnt++;
 37                 if(cnt>=3)
 38                 {
 39                     t=1;
 40                     for(R int k=j;k<j+cnt;++k)clear[i][k]=1;
 41                 }
 42             }
 43     for(R int i=1;i<=5;++i)
 44         for(R int j=1;j<=7;++j)
 45             if(clear[i][j])map[i][j]=0;
 46 }
 47 inline void Move(int ro,int co,int dir)
 48 {
 49     swap(map[ro+dir][co],map[ro][co]);Fall();
 50     t=0;
 51     do
 52     {
 53         t=0;
 54         Wipe();
 55         Fall();
 56     }while(t);
 57 }
 58 inline void dfs(int step)
 59 {
 60     if(step>n)return;
 61     if(step==n)
 62     {
 63         bool t=1;
 64         for(R int i=1;i<=5;++i)
 65             for(R int j=1;j<=7;++j)
 66                 if(map[i][j])
 67                 {
 68                     t=0;
 69                     return;
 70                 }
 71         if(t)
 72         {
 73             for(R int i=0;i<row.size();++i)printf("%d %d %d\n",row[i],col[i],dire[i]);
 74             //while(1);
 75             exit(0);
 76         }
 77         return;
 78     }
 79     memcpy(backup[step],map,sizeof(map));
 80     for(R int i=1;i<=5;++i)
 81         for(R int j=1;j<=7&&map[i][j];++j)
 82         {
 83             if(i<5&&map[i+1][j]!=map[i][j])
 84             {
 85                 row.push_back(i-1);
 86                 col.push_back(j-1);
 87                 dire.push_back(1);
 88                 Move(i,j,1);
 89                 dfs(step+1);
 90                 memcpy(map,backup[step],sizeof(map));
 91                 row.erase(row.begin()+step);
 92                 col.erase(col.begin()+step);
 93                 dire.erase(dire.begin()+step);
 94             }
 95             if(i>1&&map[i-1][j]==0&&map[i-1][j]!=map[i][j])//卧槽还有这种操作……
 96             {
 97                 row.push_back(i-1);
 98                 col.push_back(j-1);
 99                 dire.push_back(-1);
100                 Move(i,j,-1);
101                 dfs(step+1);
102                 memcpy(map,backup[step],sizeof(map));
103                 row.erase(row.begin()+step);
104                 col.erase(col.begin()+step);
105                 dire.erase(dire.begin()+step);
106             }
107         }
108     return;
109 }
110 int haha()
111 {
112     freopen("mayan.in","r",stdin);
113     freopen("mayan.out","w",stdout);
114     scanf("%d",&n);
115     for(R int i=1;i<=5;++i)
116     {
117         int x;
118         while(scanf("%d",&x)!=EOF&&x)
119             map[i][++num[i]]=x;
120     }
121     dfs(0);
122     puts("-1");
123     //while(1);
124 }
125 int sb=haha();
126 int main(){;}
A

B、Monotonicity 2

吐槽时间:你们这样做让我这个dp不会数据结构也不会的蒟蒻瑟瑟发抖……

题解:我们可以观察到状态转移方程为$f[i]=max{f[j]|j<i且符号满足条件}$,等号右边是一个最大化的式子,很明显可以用数据结构优化。我用了两棵线段树分别维护大于号小于号情况(实际是太蒻了分不清大小),神犇mk使用了两个树状数组卡常大成功,ORZ!

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 const int maxn=500005;
 7 int a[maxn],n,f[maxn],k,ans;
 8 char s[maxn];
 9 int q[maxn<<1],q1[maxn<<4],q2[maxn<<4],line[maxn];
10 void Update(int pos,int val)
11 {
12     q[pos]=max(val,q[pos]);
13 }
14 int Query(int pos)
15 {
16     return q[pos];
17 }
18 #define mid ((l+r)>>1)
19 #define lc root<<1
20 #define rc root<<1|1
21 #define lson lc,l,mid
22 #define rson rc,mid+1,r
23 void Update1(int root,int l,int r,int pos,int val)
24 {
25     if(l==r)
26     {
27         q1[root]=max(q1[root],val);
28         return;
29     }
30     if(pos<=mid)Update1(lson,pos,val);
31     else Update1(rson,pos,val);
32     q1[root]=max(q1[lc],q1[rc]);
33 }
34 int Query1(int root,int l,int r,int L,int R)
35 {
36     if(L<=l&&r<=R)return q1[root];
37     if(R<=mid)return Query1(lson,L,R);
38     else if(L>mid)return Query1(rson,L,R);
39     return max(Query1(lson,L,R),Query1(rson,L,R));
40 }
41 void Update2(int root,int l,int r,int pos,int val)
42 {
43     if(l==r)
44     {
45         q2[root]=max(q2[root],val);
46         return;
47     }
48     if(pos<=mid)Update2(lson,pos,val);
49     else Update2(rson,pos,val);
50     q2[root]=max(q2[lc],q2[rc]);
51 }
52 int Query2(int root,int l,int r,int L,int R)
53 {
54     if(L<=l&&r<=R)return q2[root];
55     if(R<=mid)return Query2(lson,L,R);
56     else if(L>mid)return Query2(rson,L,R);
57     return max(Query2(lson,L,R),Query2(rson,L,R));
58 }
59 void Add(int pos,int val)
60 {
61     if(s[line[val]]=='=')Update(pos,val);
62     else if(s[line[val]]=='<')Update1(1,0,1000001,pos,val);
63     else Update2(1,0,1000001,pos,val);
64 }
65 int haha()
66 {
67     freopen("mot.in","r",stdin);
68     freopen("mot.out","w",stdout);
69     scanf("%d%d",&n,&k);
70     for(int i=1;i<=n;i++)
71     {
72         scanf("%d",&a[i]);
73         line[i]=(i-1)%k+1;
74     }
75     for(int i=1;i<=k;i++)
76     {
77         char c=getchar();
78         while(c!='<'&&c!='>'&&c!='=')c=getchar();
79         s[i]=c;
80     }
81     f[1]=1;Add(a[1],1);
82     int ans=1;
83     for(int i=2;i<=n;i++)
84     {
85         int res=Query(a[i]),res1=Query1(1,0,1000001,0,a[i]-1),res2=Query2(1,0,1000001,a[i]+1,1000001);
86         Add(a[i],res+1);Add(a[i],res1+1);Add(a[i],res2+1);
87         f[i]=max(res,max(res1,res2))+1;
88         ans=max(ans,f[i]);
89     }
90     printf("%d\n",ans);
91     //while(1);
92 }
93 int sb=haha();
94 int main(){;}
B

C、杀人游戏

吐槽:又一道对打挂正解不友好题目……利益相关:少考虑两种(假的)特殊情况炸飞72分(稍后介绍坑点)

题解:首先我们可以想到,如果出现了一个环,这个环只会让警察冒一次险。其次,两个联通的环,警察也只需冒一次险。那么我们就可以Tarjan缩点,完成后扫一遍入度为0的点即为所求(然而wxh神犇没缩点拿下全场最高分)。

特别注意:如果一个强连通分量,里面只有一个点,这个点入度出度都为零或者它连接的点入度均不为一,我们就可以不查他,个数就要减1(炸飞72分的怨念)。

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<algorithm>
  4 #include<cstring>
  5 #include<vector>
  6 using namespace std;
  7 const int maxn=100005,maxm=300005;
  8 struct node
  9 {
 10     int from,to,next;
 11 }edge[maxm<<1];
 12 int head[maxn],tot,entrance_degree[maxn],exit_degree[maxn],size[maxn];
 13 int n,m;
 14 void addedge(int u,int v)
 15 {
 16     edge[++tot]=(node){u,v,head[u]};head[u]=tot;
 17 }
 18 int low[maxn],dfn[maxn],cnt,scnt,belong[maxn];
 19 #include<stack>
 20 stack<int>s;
 21 void dfs1(int pos)
 22 {
 23     low[pos]=dfn[pos]=++cnt;
 24     s.push(pos);
 25     for(int i=head[pos];i;i=edge[i].next)
 26     {
 27         int v=edge[i].to;
 28         if(!dfn[v])
 29         {
 30             dfs1(v);
 31             low[pos]=min(low[v],low[pos]);
 32         }
 33         else if(!belong[v])low[pos]=min(low[pos],dfn[v]);
 34     }
 35     if(low[pos]==dfn[pos])
 36     {
 37         scnt++;int k;
 38         do
 39         {
 40             k=s.top();s.pop();
 41             belong[k]=scnt;
 42             size[scnt]++;
 43         }while(k!=pos);
 44     }
 45 }
 46 bool vis[maxn];
 47 int ans;
 48 void dfs2(int from)
 49 {
 50     bool t=1;
 51     if(!exit_degree[from])t=0;
 52     for(int i=head[from];i;i=edge[i].next)
 53     {
 54         int v=edge[i].to;
 55         if(entrance_degree[v]==1)t=0;
 56         dfs2(v);
 57     }
 58     vis[from]=t;
 59 }
 60 int haha()
 61 {
 62     freopen("killer.in","r",stdin);
 63     freopen("killer.out","w",stdout);
 64     scanf("%d%d",&n,&m);
 65     for(int i=1;i<=m;i++)
 66     {
 67         int x,y;scanf("%d%d",&x,&y);
 68         addedge(x,y);
 69     }
 70     for(int i=1;i<=n;i++)
 71         if(!dfn[i])dfs1(i);
 72     memset(head,0,sizeof(head));
 73     for(int i=1;i<=m;i++)
 74     {
 75         int u=edge[i].from,v=edge[i].to;
 76         u=belong[u],v=belong[v];
 77         if(u!=v)
 78         {
 79             addedge(u,v);
 80             exit_degree[u]++;
 81             entrance_degree[v]++;
 82         }
 83     }
 84     ans=0;
 85     for(int i=1;i<=scnt;i++)
 86         if(!entrance_degree[i])
 87         {
 88             ans++;
 89             dfs2(i);
 90         }
 91     for(int i=1;i<=scnt;i++)
 92         if((vis[i]||(!entrance_degree[i]&&!exit_degree[i]))&&size[i]==1)//俩特殊情况挂飞72分……想死……
 93         {
 94             ans--;
 95             break;
 96         }
 97     printf("%0.6lf\n",1.0-(ans*1.0)/(n*1.0));
 98 }
 99 int sb=haha();
100 int main(){;}
C

D、弱题

吐槽:果然弱题,对迭代这么友好……

题解:暴力推式子可以得到$f[x][now]=f[x][last]-f[x][last]/m+f[x-1][last]/m$,k极大,天然的矩阵优化(然而你考试不一样是迭代加精度优化),但是注意到n<=1000,矩阵快速幂绝对炸飞(还没我分高),于是我们采用奇技淫巧:

(原图错了凑合看吧)

可以看到,每一行都相当于上一行向右平移得到的,于是我们只维护第一行,随后递推出下面几行就行了。

改题这么富裕的时间都能把double打成int,AFO得了,世界再见

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<cmath>
 6 using namespace std;
 7 const int maxn=1005;
 8 const double eps=1e-8;
 9 int m,n,k;
10 struct Matrix
11 {
12     double a[1005][1005];
13 }Ans,x;
14 double tmp[maxn];//……写成int……我还能说点啥……世界再见……
15 __attribute__((optimize("O3")))void qpow(Matrix p,int tim)
16 {
17     for(;tim;tim>>=1)
18     {
19         if(tim&1)
20         {
21             for(int i=1;i<=n;i++)tmp[i]=0;
22             for(int i=1;i<=n;i++)
23                 for(int j=1;j<=n;j++)tmp[i]+=x.a[1][j]*Ans.a[j][i];
24             for(int i=1;i<=n;i++)x.a[1][i]=tmp[i];
25         }
26         for(int i=1;i<=n;i++)tmp[i]=0;
27         for(int i=1;i<=n;i++)
28             for(int j=1;j<=n;j++)tmp[i]+=Ans.a[1][j]*Ans.a[j][i];
29         for(int i=1;i<=n;i++)Ans.a[1][i]=tmp[i];
30         for(int i=2;i<=n;i++)
31             for(int j=1;j<=n;j++)
32                 if(j==1)Ans.a[i][j]=Ans.a[i-1][n];
33                 else Ans.a[i][j]=Ans.a[i-1][j-1];
34     }
35 }
36 __attribute__((optimize("O3")))int haha()
37 {
38     //freopen("data.in","r",stdin);
39     //freopen("data.out","w",stdout);
40     scanf("%d%d%d",&n,&m,&k);
41     for(int i=1;i<=n;i++)scanf("%lf",&x.a[1][i]);
42     double p1=1.0-(1.0/(m*1.0)),p2=1.0/(m*1.0);
43     for(int i=1;i<=n;i++)
44         if(i==n)
45         {
46             Ans.a[n][n]=p1;
47             Ans.a[n][1]=p2;
48         }
49         else
50         {
51             Ans.a[i][i]=p1;
52             Ans.a[i][i+1]=p2;
53         }
54     qpow(Ans,k);
55     for(int i=1;i<=n;i++)printf("%0.3lf\n",x.a[1][i]);
56 }
57 int sb=haha();
58 __attribute__((optimize("O3")))int main(){;}
D

(不要在意那个O3……那不是重点……)

posted @ 2017-07-27 21:46  ccc000111  阅读(180)  评论(0编辑  收藏  举报