[关闭]
@happyforever 2018-10-31T12:49:32.000000Z 字数 10327 阅读 523

10.28下午解题报告

清北学堂 解题报告


各题状况

期望得分:
实际得分:

题目及考场代码

T1

图片.png

  1. /*
  2. * 拿上暴力分就跑
  3. * 真TM刺激
  4. * 吔
  5. */
  6. #include <map>
  7. #include <cstdio>
  8. #include <string>
  9. #include <iostream>
  10. const int N=101,mod=1e9+7;
  11. int n,len,ans;
  12. std::string s,emp;
  13. std::map<std::string,bool> mp;
  14. void dfs(int now,int tot)
  15. {
  16. if(now==n)
  17. {
  18. if(tot!=len)return ;
  19. int tot=0;
  20. for(int i=0;i<n;++i)
  21. {
  22. if(emp[i]=='(')
  23. ++tot;
  24. else
  25. if(tot)
  26. --tot;
  27. else return ;
  28. }
  29. if(!tot && !mp[emp])
  30. {
  31. // std::cout<<emp<<std::endl;
  32. mp[emp]=true;
  33. ++ans;
  34. }
  35. return ;
  36. }
  37. emp[now]='(';
  38. dfs(now+1,tot);
  39. emp[now]=')';
  40. dfs(now+1,tot);
  41. emp[now]=s[tot];
  42. dfs(now+1,tot+1);
  43. }
  44. int main()
  45. {
  46. freopen("regular.in","r",stdin);
  47. freopen("regular.out","w",stdout);
  48. scanf("%d",&n);n<<=1;
  49. for(int i=0;i<n;++i)
  50. emp.push_back('*');
  51. std::cin>>s;
  52. len=s.size();
  53. dfs(0,0);
  54. printf("%d",ans);
  55. fclose(stdin);fclose(stdout);
  56. return 0;
  57. }

T2

图片.png

  1. /*
  2. * 考虑记录读入的n个数,按从小到大排序之后看做数轴上的很多点
  3. * 考虑每次操作可以看做将数轴上一段区间变为一个点
  4. * 由于本题的各种操作时按顺序来的。。。。
  5. * 应该是相当于强制在线?
  6. * 反正不会
  7. * 可能是dp
  8. *
  9. * 吔
  10. */
  11. #include <cstdio>
  12. #include <algorithm>
  13. const int inf=0x7f7f7f7f;
  14. int n,m,ans=inf;
  15. int num[1010];
  16. struct Node{
  17. int l,r,x;
  18. bool operator<(const Node &gg)const
  19. {
  20. if(x==gg.x)
  21. {
  22. if(l==gg.l)
  23. return r<gg.r;
  24. return l<gg.l;
  25. }
  26. return x<gg.x;
  27. }
  28. }v[100010],vv[10010];
  29. inline int max(int x,int y)
  30. {return x>y?x:y;}
  31. inline int min(int x,int y)
  32. {return x<y?x:y;}
  33. inline int read()
  34. {
  35. int n=0,w=1;register char c=getchar();
  36. while(c<'0' || c>'9'){if(c=='-')w=-1;c=getchar();}
  37. while(c>='0' && c<='9')n=n*10+c-'0',c=getchar();
  38. return n*w;
  39. }
  40. /*
  41. void dfs(int now,int step)
  42. {
  43. if(now>m)
  44. {
  45. for(int i=2;i<=n;++i)
  46. if(a[i]!=a[i-1])
  47. return ;
  48. ans=min(ans,step);
  49. return ;
  50. }
  51. int l=work[now].l,r=work[now].r,x=work[now].x;
  52. for(int i=l;i<=r;++i)
  53. a[i]=x;
  54. dfs(now+1,step+1);
  55. for(int i=l;i<=r;++i)
  56. a[i]=i;
  57. dfs(now+1,step);
  58. }
  59. */
  60. bool judge(int tot)
  61. {
  62. for(int i=1;i<=tot;++i)
  63. vv[i]=v[num[i]];
  64. for(int i=1;i<=tot;++i)
  65. for(int j=1;j<i;++j)
  66. if(vv[i].x>=vv[j].l&&vv[i].x<=v[j].r)
  67. vv[i].x==vv[j].x;
  68. std::sort(vv+1,vv+1+tot);
  69. int l=0,r=0;
  70. for(int i=1;i<=tot;++i)
  71. {
  72. if(vv[i].x!=vv[i-1].x)
  73. {
  74. if(l==1 && r==n)
  75. return true;
  76. l=vv[i].l;r=vv[i].r;
  77. continue;
  78. }
  79. if(vv[i].l<=r) r=max(vv[i].r,r);
  80. }
  81. return l==1 && r==n;
  82. }
  83. void dfs(int now,int tot)
  84. {
  85. if(now>m)
  86. {
  87. if(judge(tot))
  88. ans=min(ans,tot);
  89. return ;
  90. }
  91. num[tot+1]=now;
  92. dfs(now+1,tot+1);
  93. num[tot+1]=0;
  94. dfs(now+1,tot);
  95. }
  96. int main()
  97. {
  98. freopen("number.in","r",stdin);
  99. freopen("number.out","w",stdout);
  100. n=read(),m=read();
  101. for(int i=1;i<=m;i++)
  102. v[i]=(Node){read(),read(),read()};
  103. if(n<=10)
  104. dfs(1,0);
  105. printf("%d",ans==inf?-1:ans);
  106. fclose(stdin);fclose(stdout);
  107. return 0;
  108. }

T3

图片.png

  1. /*
  2. * 如果不是i~j而是i,j的话就是原题。
  3. * 问删掉某条边之后又多少连续区间在同一联通块内。
  4. *
  5. * 只会暴力qwq
  6. */
  7. #include<cstdio>
  8. const int N=1001;
  9. int n,head[N],ans,tot;
  10. bool vis[N];
  11. struct Edge{
  12. int v,nxt;
  13. }edge[N<<1];
  14. inline int read()
  15. {
  16. int n=0,w=1;register char c=getchar();
  17. while(c<'0' || c>'9'){if(c=='-')w=-1;c=getchar();}
  18. while(c>='0' && c<='9')n=n*10+c-'0',c=getchar();
  19. return n*w;
  20. }
  21. inline void add(int v,int u)
  22. {
  23. edge[++tot]=(Edge){v,head[u]};head[u]=tot;
  24. edge[++tot]=(Edge){u,head[v]};head[v]=tot;
  25. }
  26. bool color,col[N];
  27. void dfs(int now,int fa)
  28. {
  29. col[now]=color;
  30. for(int v,i=head[now];i;i=edge[i].nxt)
  31. if((v=edge[i].v)!=fa)
  32. dfs(v,now);
  33. }
  34. void work()
  35. {
  36. for(int i=1;i<=tot;++++i)
  37. {
  38. // printf("%d %d\n",edge[i].v,edge[i+1].v);
  39. color=false;
  40. col[edge[i+1].v]=false;
  41. for(int j=head[edge[i+1].v];j;j=edge[j].nxt)
  42. if(j!=i && j!=i+1)
  43. dfs(edge[j].v,edge[i+1].v);
  44. color=true;
  45. col[edge[i].v]=true;
  46. for(int j=head[edge[i].v];j;j=edge[j].nxt)
  47. if(j!=i && j!=i+1)
  48. dfs(edge[j].v,edge[i].v);
  49. /*
  50. for(int j=1;j<=n;++j)
  51. printf("%d ",col[j]?1:0);
  52. puts("");
  53. */
  54. for(int j=1;j<=n;++j)
  55. for(int k=j;col[j]==col[k] && k<=n;++k)
  56. ++ans;
  57. }
  58. printf("%d",ans);
  59. }
  60. int main()
  61. {
  62. freopen("sum.in","r",stdin);
  63. freopen("sum.out","w",stdout);
  64. n=read();
  65. for(int i=1;i<n;++i)
  66. add(read(),read());
  67. work();
  68. fclose(stdin); fclose(stdout);
  69. return 0;
  70. }

正解及代码

原题中要求方案不重复,先考虑加的括号是红色的,原有的括号是黑色的
表示现在用了个红括号,个黑括号,左括号比右括号多个。
1. 个黑色括号是右括号

2. 个红色括号是右括号

3. 第个黑色括号是左括号

4. 第个黑色括号是左括号


但是对于原题不可行。


即:如果可以使用黑色,就优先使用黑色,这样方案不重不漏。

  1. #include<iostream>
  2. #include<algorithm>
  3. #include<cstdio>
  4. #include<cstring>
  5. #include<string>
  6. #include<cmath>
  7. #include<cstdlib>
  8. #include<ctime>
  9. using namespace std;
  10. typedef long long ll;
  11. typedef long double ld;
  12. typedef pair<int,int> pr;
  13. const double pi=acos(-1);
  14. #define rep(i,a,n) for(int i=a;i<=n;i++)
  15. #define per(i,n,a) for(int i=n;i>=a;i--)
  16. #define Rep(i,u) for(int i=head[u];i;i=Next[i])
  17. #define clr(a) memset(a,0,sizeof a)
  18. #define pb push_back
  19. #define mp make_pair
  20. ld eps=1e-9;
  21. ll pp=1000000007;
  22. ll mo(ll a,ll pp){if(a>=0 && a<pp)return a;a%=pp;if(a<0)a+=pp;return a;}
  23. ll powmod(ll a,ll b,ll pp){ll ans=1;for(;b;b>>=1,a=mo(a*a,pp))if(b&1)ans=mo(ans*a,pp);return ans;}
  24. ll read(){
  25. ll ans=0;
  26. char last=' ',ch=getchar();
  27. while(ch<'0' || ch>'9')last=ch,ch=getchar();
  28. while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar();
  29. if(last=='-')ans=-ans;
  30. return ans;
  31. }
  32. //head
  33. #define N 210
  34. const int p=1000000007;
  35. int n,m,s[N],ch[N][2],f[N],dp[N][N][N];
  36. char str[N];
  37. void add(int &a,int b){
  38. a+=b;
  39. if(p<=a)a-=p;
  40. }
  41. int main(){
  42. freopen("regular.in","r",stdin);
  43. freopen("regular.out","w",stdout);
  44. n=read();
  45. scanf("%s",str),m=strlen(str);
  46. dp[0][0][0]=1;
  47. rep(i,0,2*n-m)
  48. rep(j,0,m)
  49. rep(k,0,n)
  50. if(dp[i][j][k]){
  51. if(j<m && str[j]=='(')add(dp[i][j+1][k+1],dp[i][j][k]);
  52. else add(dp[i+1][j][k+1],dp[i][j][k]);
  53. if(k>0){
  54. if(j<m && str[j]==')')add(dp[i][j+1][k-1],dp[i][j][k]);
  55. else add(dp[i+1][j][k-1],dp[i][j][k]);
  56. }
  57. }
  58. cout<<dp[2*n-m][m][0]<<endl;
  59. return 0;
  60. }

T2

图片.png
考虑题目实际是给了一些漏斗,要求选出最少的漏斗使得在任意位置扔都能漏到同一个位置

首先离散化。“所有数字变为相同的数字”等价于“变为相同的数字”。记录行数,从第一列下落的目前所在列,从第列下落的目前所在列这三个量即可。复杂度是

可以发现上一个做法记录的后两个状态互不影响(在到最后一个漏斗之前两个位置是不相交不交错的),可以分别计算从经过前个操作变成j所需的最小花费数,对于n也类似这样做,找答案时只需枚举最后一个操作即可。复杂度

的解法基础上用线段树进行维护,时间复杂度

  1. #include<iostream>
  2. #include<algorithm>
  3. #include<cstdio>
  4. #include<cstring>
  5. #include<string>
  6. #include<cmath>
  7. #include<cstdlib>
  8. #include<ctime>
  9. using namespace std;
  10. typedef long long ll;
  11. typedef long double ld;
  12. typedef pair<int,int> pr;
  13. const double pi=acos(-1);
  14. #define rep(i,a,n) for(int i=a;i<=n;i++)
  15. #define per(i,n,a) for(int i=n;i>=a;i--)
  16. #define Rep(i,u) for(int i=head[u];i;i=Next[i])
  17. #define clr(a) memset(a,0,sizeof a)
  18. #define pb push_back
  19. #define mp make_pair
  20. ld eps=1e-9;
  21. ll pp=1000000007;
  22. ll mo(ll a,ll pp){if(a>=0 && a<pp)return a;a%=pp;if(a<0)a+=pp;return a;}
  23. ll powmod(ll a,ll b,ll pp){ll ans=1;for(;b;b>>=1,a=mo(a*a,pp))if(b&1)ans=mo(ans*a,pp);return ans;}
  24. ll read(){
  25. ll ans=0;
  26. char last=' ',ch=getchar();
  27. while(ch<'0' || ch>'9')last=ch,ch=getchar();
  28. while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar();
  29. if(last=='-')ans=-ans;
  30. return ans;
  31. }
  32. //head
  33. const ll INF=(ll)1<<60;
  34. #define N 110000
  35. int n,m,a[N],b[N],c[N],q[N];
  36. ll ans=INF;
  37. struct seg{
  38. ll Min[N*4],a[N];
  39. void build(int u,int l,int r){
  40. if(l==r){
  41. Min[u]=a[l];
  42. return;
  43. }
  44. int mid=(l+r)>>1;
  45. build(u*2,l,mid);
  46. build(u*2+1,mid+1,r);
  47. Min[u]=min(Min[u*2],Min[u*2+1]);
  48. }
  49. ll find(int u,int l,int r,int x,int y){
  50. if(x<=l && y>=r)return Min[u];
  51. if(x>r || y<l)return INF;
  52. int mid=(l+r)>>1;
  53. return min(find(u*2,l,mid,x,y),find(u*2+1,mid+1,r,x,y));
  54. }
  55. void change(int u,int l,int r,int x,ll w){
  56. if(l==r){
  57. Min[u]=min(w,Min[u]);
  58. return;
  59. }
  60. int mid=(l+r)>>1;
  61. if(x<=mid)change(u*2,l,mid,x,w);
  62. else change(u*2+1,mid+1,r,x,w);
  63. Min[u]=min(Min[u*2],Min[u*2+1]);
  64. }
  65. }t1,t2;
  66. int bin1(int k){
  67. int l=1,r=q[0];
  68. while(l<r){
  69. int mid=(l+r)/2;
  70. if(q[mid]>=k)r=mid;
  71. else l=mid+1;
  72. }
  73. return l;
  74. }
  75. int bin2(int k){
  76. int l=1,r=q[0];
  77. while(l<r){
  78. int mid=(l+r)/2+1;
  79. if(k>=q[mid])l=mid;
  80. else r=mid-1;
  81. }
  82. return l;
  83. }
  84. int main(){
  85. freopen("number.in","r",stdin);
  86. freopen("number.out","w",stdout);
  87. m=read();n=read();
  88. q[++q[0]]=1;
  89. q[++q[0]]=m;
  90. rep(i,1,n)a[i]=read(),b[i]=read(),c[i]=read(),q[++q[0]]=c[i];
  91. sort(q+1,q+q[0]+1);
  92. q[0]=1;
  93. rep(i,2,n+2)
  94. if(q[i]!=q[q[0]])q[++q[0]]=q[i];
  95. m=q[0];
  96. rep(i,1,q[0]){
  97. t1.a[i]=INF*(int)(i>1);
  98. t2.a[i]=INF*(int)(i<q[0]);
  99. }
  100. t1.build(1,1,q[0]);
  101. t2.build(1,1,q[0]);
  102. rep(i,1,n){
  103. a[i]=bin1(a[i]);
  104. b[i]=bin2(b[i]);
  105. c[i]=bin1(c[i]);
  106. ll f1=t1.find(1,1,q[0],a[i],b[i]),f2=t2.find(1,1,q[0],a[i],b[i]);
  107. ans=min(f1+f2+1,ans);
  108. t1.change(1,1,q[0],c[i],f1+1);
  109. t2.change(1,1,q[0],c[i],f2+1);
  110. }
  111. if(ans<INF)cout<<ans<<endl;
  112. else cout<<-1<<endl;
  113. return 0;
  114. }

T3

set启发式合并维护每棵子树内的编号,以表示是否在子树内,以的形式成段的记录在set中,每次修改一个位置时最多只需考虑set中相邻两个。

  1. #include<iostream>
  2. #include<algorithm>
  3. #include<cstdio>
  4. #include<cstring>
  5. #include<cmath>
  6. #include<cstdlib>
  7. #include<set>
  8. using namespace std;
  9. typedef long long ll;
  10. typedef long double ld;
  11. typedef pair<int,int> pr;
  12. const double pi=acos(-1);
  13. #define rep(i,a,n) for(int i=a;i<=n;i++)
  14. #define per(i,n,a) for(int i=n;i>=a;i--)
  15. #define Rep(i,u) for(int i=head[u];i;i=Next[i])
  16. #define clr(a) memset(a,0,sizeof a)
  17. #define pb push_back
  18. #define mp make_pair
  19. #define fi first
  20. #define sc second
  21. ld eps=1e-9;
  22. ll pp=1000000007;
  23. ll mo(ll a,ll pp){if(a>=0 && a<pp)return a;a%=pp;if(a<0)a+=pp;return a;}
  24. ll powmod(ll a,ll b,ll pp){ll ans=1;for(;b;b>>=1,a=mo(a*a,pp))if(b&1)ans=mo(ans*a,pp);return ans;}
  25. ll read(){
  26. ll ans=0;
  27. char last=' ',ch=getchar();
  28. while(ch<'0' || ch>'9')last=ch,ch=getchar();
  29. while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar();
  30. if(last=='-')ans=-ans;
  31. return ans;
  32. }
  33. //head
  34. set<int>Q;
  35. set<int>::iterator it,it1,it2;
  36. #define N 210000
  37. int head[N],v[N],fa[N],Next[N],k[N],f[N],s[N],son[N],siz[N],n,num,q[N],q2[N];
  38. bool vis[N];
  39. ll Ans,sum1,sum2;
  40. void add(int x,int y){
  41. v[++num]=y;
  42. Next[num]=head[x];
  43. head[x]=num;
  44. }
  45. ll f1(ll x){return x*(x+1)/2;};
  46. void dfs1(int u){
  47. int t=0,w=1;
  48. q[1]=u;
  49. while(t<w){
  50. int u=q[++t];
  51. siz[u]=1;
  52. for(int i=head[u];i;i=Next[i])
  53. if(v[i]!=fa[u]){
  54. fa[v[i]]=u;
  55. q[++w]=v[i];
  56. }
  57. }
  58. per(i,w,2){
  59. int u=q[i];
  60. siz[fa[u]]+=siz[u];
  61. if(siz[u]>siz[son[fa[u]]] || son[fa[u]]==0)son[fa[u]]=u;
  62. }
  63. }
  64. int find(int u){
  65. if(u==f[u])return u;
  66. return f[u]=find(f[u]);
  67. }
  68. void add(int u){
  69. k[u]=1;
  70. sum1++;
  71. if(k[u-1] && find(u-1)!=find(u)){
  72. int x=find(u-1),y=find(u);
  73. sum1+=1ll*s[x]*s[y];
  74. f[x]=y;
  75. s[y]+=s[x];
  76. }
  77. if(k[u+1] && find(u+1)!=find(u)){
  78. int x=find(u+1),y=find(u);
  79. sum1+=1ll*s[x]*s[y];
  80. f[x]=y;
  81. s[y]+=s[x];
  82. }
  83. Q.insert(u);
  84. it=Q.find(u);
  85. it1=it;
  86. it2=it;
  87. --it1;
  88. ++it2;
  89. sum2-=f1((*it2)-(*it1)-1);
  90. sum2+=f1((*it)-(*it1)-1);
  91. sum2+=f1((*it2)-(*it)-1);
  92. }
  93. void dfs3(int u){
  94. int t=0,w=1;
  95. q[1]=u;
  96. while(t<w){
  97. int u=q[++t];
  98. f[u]=u;s[u]=1;k[u]=0;
  99. for(int i=head[u];i;i=Next[i])
  100. if(v[i]!=fa[u])q[++w]=v[i];
  101. }
  102. }
  103. void dfs4(int u){
  104. int t=0,w=1;
  105. q[1]=u;
  106. while(t<w){
  107. int u=q[++t];
  108. add(u);
  109. for(int i=head[u];i;i=Next[i])
  110. if(v[i]!=fa[u])q[++w]=v[i];
  111. }
  112. }
  113. void clear(int u){
  114. Q.clear();
  115. Q.insert(0);
  116. Q.insert(n+1);
  117. sum1=0;
  118. sum2=f1(n);
  119. dfs3(u);
  120. }
  121. void dfs2(int u){
  122. int t=0,w=1;
  123. q2[1]=u;
  124. while(t<w){
  125. int u=q2[++t];vis[u]=0;
  126. for(int i=head[u];i;i=Next[i])
  127. if(v[i]!=fa[u])q2[++w]=v[i];
  128. }
  129. per(j,w,1)
  130. if(!vis[q2[j]]){
  131. int u=q2[j];
  132. while(!vis[u]){
  133. vis[u]=1;
  134. add(u);
  135. for(int i=head[u];i;i=Next[i])
  136. if(v[i]!=son[u] && v[i]!=fa[u])dfs4(v[i]);
  137. Ans+=f1(n)-sum1-sum2;
  138. if(fa[u]==0 || son[fa[u]]!=u)break;
  139. u=fa[u];
  140. }
  141. clear(u);
  142. }
  143. }
  144. int main(){
  145. freopen("sum.in","r",stdin);
  146. freopen("sum.out","w",stdout);
  147. n=read();
  148. Q.clear();
  149. Q.insert(0);
  150. Q.insert(n+1);
  151. sum1=0;
  152. sum2=f1(n);
  153. rep(i,1,n)f[i]=i,s[i]=1,k[i]=0;
  154. rep(i,2,n){
  155. int x=read(),y=read();
  156. add(x,y);
  157. add(y,x);
  158. }
  159. dfs1(1);
  160. dfs2(1);
  161. cout<<f1(n)*(n-1)-Ans<<endl;
  162. return 0;
  163. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注