Day2下午解题报告
预计分数:100+100+30=230
实际分数:100+100+30=230
人品爆发&&智商爆发&&手感爆发
T3数据好水,,要是把数组开大一点的话还能多得10分,,,
T1洗澡
原题,不多说了。。
当时在北京花了接近一个小时才A..
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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-这个值之间二分,
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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("%d\n",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("%lld\n",out); 58 else printf("-1\n"); 59 } 60 return 0; 61 }
T3洗衣
直觉告诉我,这题一定非常难,,
因为我连暴力都不会打,
想了几分钟,感觉30分可以做,就是比较奇葩,,,需要存2^m棵树,
代码很恶心,,不过还好没敲炸
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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("%d\n",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
作者:自为风月马前卒
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。