Day2下午解题报告

2018-04-11 16:27:38 浏览数 (1)

预计分数:100 100 30=230

实际分数:100 100 30=230 人品爆发&&智商爆发&&手感爆发

T3数据好水,,要是把数组开大一点的话还能多得10分,,,

T1洗澡

原题,不多说了。。

当时在北京花了接近一个小时才A..

代码语言:javascript复制
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<cmath>
 5 using namespace std;
 6 const int MAXN=1e6;
 7 const int INF=0x7ffff;
 8 inline int read()
 9 {
10     char c=getchar();int flag=1,x=0;
11     while(c<'0'||c>'9')    {if(c=='-')    flag=-1;c=getchar();}
12     while(c>='0'&&c<='9')     x=x*10 c-48,c=getchar();return x*flag;
13 }
14 char a[MAXN];
15 int main()
16 {
17     //freopen("shower.in","r",stdin);
18     //freopen("shower.out","w",stdout);
19     scanf("%s",a 1);
20     int l=strlen(a 1);
21     int now=0,ans=0;
22     for(int i=1;i<=l;i  )
23     {
24         if(a[i]=='(')
25         {
26             if(now==l/2)    ans  ,now--;//修改 
27             else now  ;
28         }
29         else
30         {
31             if(now==0)    ans  ,now  ;
32             else if(now<=l/2)    now--;
33         }
34     }
35     printf("%d",ans now/2);
36     return 0;
37 }

T2日记

一开始想到了70分的做法,写着写着就会100分的做法了。。

先打个素数表,

对于每次询问的n

upperbound一个值,再在k-这个值之间二分,

代码语言:javascript复制
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<cmath>
 5 #include<algorithm>
 6 #define LL long long 
 7 using namespace std;
 8 const LL MAXN=1e6 10;
 9 const LL INF=0x7ffff;
10 inline LL read()
11 {
12     char c=getchar();LL flag=1,x=0;
13     while(c<'0'||c>'9')    {if(c=='-')    flag=-1;c=getchar();}
14     while(c>='0'&&c<='9')     x=x*10 c-48,c=getchar();return x*flag;
15 }
16 LL T;
17 LL vis[MAXN];
18 LL prime[MAXN];
19 LL sprime[MAXN];
20 LL tot=0;
21 LL check(LL mid,LL n,LL k)
22 {
23     if(sprime[mid]-sprime[mid-k]<=n)    return 1;
24     else                             return 0;
25 }
26 int main()
27 {
28 //    freopen("diary.in","r",stdin);
29 //    freopen("diary.out","w",stdout);
30     for(LL i=2;i<=sqrt(1e6);i  )
31     {
32         if(vis[i]==0)
33             for(LL j=i*i;j<=1e6;j =i)
34                 vis[j]=1;
35     }
36     for(LL i=2;i<=1e6;i  )    if(vis[i]==0)    
37         prime[  tot]=i;
38     //for(LL i=1;i<=tot;i  )
39     //    printf("%dn",prime[i]);
40     T=read();
41     for(LL i=1;i<=tot;i  )
42         sprime[i]=sprime[i-1] prime[i];
43     while(T--)
44     {
45         LL n=read(),k=read();
46         LL pos=upper_bound(prime 1,prime tot 1,n)-prime;pos--;
47         LL ans=0;
48         bool flag=0;
49         LL l=k,r=pos;
50         while(l<=r)
51         {
52             LL mid=l r>>1;
53             if(check(mid,n,k))    flag=1,ans=mid,l=mid 1;
54             else r=mid-1;
55         }
56         LL out=sprime[ans]-sprime[ans-k];
57         if(flag==1)    printf("%lldn",out);
58         else         printf("-1n");
59     }
60     return 0;
61 }

T3洗衣

直觉告诉我,这题一定非常难,,

因为我连暴力都不会打,

想了几分钟,感觉30分可以做,就是比较奇葩,,,需要存2^m棵树,

代码很恶心,,不过还好没敲炸

代码语言:javascript复制
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<cmath>
 5 #include<queue>
 6 
 7 using namespace std;
 8 const int MAXN=1001;
 9 const int INF=0x7ffff;
10 const int mod=1e9 7;
11 inline int read()
12 {
13     char c=getchar();int flag=1,x=0;
14     while(c<'0'||c>'9')    {if(c=='-')    flag=-1;c=getchar();}
15     while(c>='0'&&c<='9')     x=x*10 c-48,c=getchar();return x*flag;
16 }
17 struct TREE
18 {
19     struct node
20     {
21         int u,v,w,nxt;
22     }edge[MAXN];
23     int head[MAXN];
24     int num;
25     int siz;//树的大小 
26     int bg;//第一个节点的编号 
27     TREE()
28     {
29         memset(head,-1,sizeof(head));
30         num=1;siz=1;bg=1;
31     }
32     void add_edge(int x,int y,int z)
33     {
34         edge[num].u=x;
35         edge[num].v=y;
36         edge[num].w=z;
37         edge[num].nxt=head[x];
38         head[x]=num  ;
39     }
40 }tree[MAXN];
41 int treenum=0;
42 inline void merge(int t1,int n1,int t2,int n2,int val)
43 {
44     treenum  ;
45     for(int i=1;i<=tree[t1].num-1;i  )
46         tree[treenum].add_edge(tree[t1].edge[i].u,tree[t1].edge[i].v,tree[t1].edge[i].w);
47     for(int i=1;i<=tree[t2].num-1;i  )
48         tree[treenum].add_edge(tree[t2].edge[i].u tree[t1].siz,tree[t2].edge[i].v tree[t1].siz,tree[t2].edge[i].w);
49     tree[treenum].add_edge(n1,n2 tree[t1].siz,val);
50     tree[treenum].add_edge(n2 tree[t1].siz,n1,val);
51     tree[treenum].siz=tree[t1].siz tree[t2].siz;
52 }
53 int dis[MAXN];
54 int vis[MAXN];
55 int ans=0;
56 inline void BFS()
57 {
58     for(int k=0;k<=tree[treenum].siz-1;k  )
59     {
60         memset(dis,0,sizeof(dis));
61         memset(vis,0,sizeof(vis));
62         dis[k]=0;
63         queue<int>q;
64         q.push(k);
65         while(q.size()!=0)
66         {
67             int p=q.front();
68             q.pop();
69             for(int i=tree[treenum].head[p];i!=-1;i=tree[treenum].edge[i].nxt)
70                 if(vis[tree[treenum].edge[i].v]==0)
71                     vis[tree[treenum].edge[i].v]=1,
72                     dis[tree[treenum].edge[i].v]=(dis[p] tree[treenum].edge[i].w)%mod,
73                     q.push(tree[treenum].edge[i].v);
74         }
75         for(int i=k 1;i<=tree[treenum].siz-1;i  )
76             ans=(ans dis[i])%mod;
77     }
78 }
79 int main()
80 {
81 //    freopen("cloth.in","r",stdin);
82 //    freopen("cloth.out","w",stdout);
83     int n=read();
84     for(int i=1;i<=n;i  )
85     {
86         int a=read(),b=read(),c=read(),d=read(),e=read();
87         merge(a,c,b,d,e);
88         ans=0;
89         BFS();
90         printf("%dn",ans);
91     }
92     return 0;
93 }

100分

考虑每一棵树的组成

一棵树的答案一定包含了左边的树的答案

f[i]=f[j] f[k] dis[new]

考虑如何计算dis[new]

dis[i]=原来的j 新加的(左边树的大小*右边树的大小) 原来的k

原来的j=siz[j]*所有点到p1点的距离

k=siz[k] g[k][p2]//g在第k棵树中所有点到达p的距离

考虑如何求g

dp

设i是由j,k合并而来

g[i][p]=g[j][p] L dis[j][p][p1]*siz[k] g[k][p2]

——》会T会boom——》开map做记忆化搜索

dis[j][p][p3] l dis[k][p2][p4]记忆化搜索

总结:

这次考的好是有诸多方面的原因的。。

T1原题,T2不难,T3正解非常难,暴力需要较强的代码能力

这一套题貌似就是为我量身定做的啊233333

0 人点赞