BAPC2018做题记录
A.
签到题。排序后贪心。
1 #include <bits/stdc++.h> 2 3 using namespace std; 4 5 const int MAXN = 100000 + 10; 6 7 int n, x; 8 int a[MAXN]; 9 10 int main() { 11 ios::sync_with_stdio(false); 12 13 cin >> n >> x; 14 for (int i = 1; i <= n; ++i) 15 cin >> a[i]; 16 17 sort(a + 1, a + 1 + n); 18 19 int s = 1; 20 for (int i = 2; i <= n; ++i) { 21 if (a[i - 1] + a[i] > x) 22 break; 23 s++; 24 } 25 cout << s << endl; 26 }
B.
直接模拟。码农题。
#include <bits/stdc++.h> using namespace std; const int MAXN = 100 + 10; struct Date { int month; int day; bool operator<(const Date& a) const { return month == a.month ? day < a.day : month < a.month; } bool operator==(const Date& a) const { return a.month == month && day == a.day; } int operator-(const Date& a) const { const int DAY_PER_MONTH[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; Date A = *this; Date B = a; int ans = 0; bool flg = false; if (A < B) { swap(A, B); flg = true; } if (A.month == B.month) { ans = A.day - B.day; } else { ans = DAY_PER_MONTH[B.month] - B.day + 1; for (int i = B.month + 1; i < A.month; ++i) { ans += DAY_PER_MONTH[i]; } ans += A.day - 1; } if (flg) { ans = 365 - ans; } return ans; } Date(int m=0, int d=0): month(m), day(d) {} Date yesterday() { const int DAY_PER_MONTH[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; int m = month; int d = day - 1; if (d == 0) { m--; if (m == 0) { m = 12; } d = DAY_PER_MONTH[m]; } return Date(m, d); } } p[MAXN]; int main() { ios::sync_with_stdio(false); int n; cin >> n; for (int i = 1; i <= n; ++i) { string s; cin >> s; cin >> s; p[i] = Date((s[0] - '0') * 10 + (s[1] - '0'), (s[3] - '0') * 10 + (s[4] - '0') ); } sort(p + 1, p + 1 + n); n = unique(p + 1, p + 1 + n) - p - 1; Date today = Date(10, 28); p[0] = p[n]; Date ans; int cnt = -1; for (int i = 1; i <= n; ++i) { int dist = p[i].yesterday() - p[i - 1]; if (dist > cnt) { ans = p[i].yesterday(); cnt = dist; } else if (dist == cnt && p[i].yesterday() - today < ans - today) { ans = p[i].yesterday(); } } cout << (ans.month < 10 ? "0" : "") << ans.month << '-' << (ans.day < 10 ? "0" : "") << ans.day << endl; }
C.
枚举体积的因数,即枚举每一组长宽高并更新答案
1 #include<bits/stdc++.h> 2 using namespace std; 3 int n,ans=1e9; 4 int main(){ 5 scanf("%d",&n); 6 int stp=sqrt(n); 7 for(int i=1;i<=stp;i++){ 8 if(n%i==0){ 9 int now=n/i; 10 for(int j=1;j<=stp;j++){ 11 if(now%j==0)ans=min(ans,2*(i*j+n/i+n/j)); 12 } 13 for(int j=1;j<=i;j++){ 14 if(i%j==0)ans=min(ans,2*(now*j+n/now+n/j)); 15 } 16 } 17 } 18 printf("%d\n",ans); 19 }
D.
bfs+并查集。如果A和B无法区分,B和C无法区分,则A和C也无法区分。依据这个性质我们可以把无法区分的状态压缩起来用并查集维护。
#include <bits/stdc++.h> using namespace std; const int MAXN = 100000 + 10; int par[MAXN]; struct Intersection { int l, r, visible; } p[MAXN]; struct Node { int a, b, step; Node(int a=0, int b=0, int s=0): a(a), b(b), step(s) {} }; int find(int u) { return u == par[u] ? u : par[u] = find(par[u]); } void merge(int u, int v) { u = find(u), v = find(v); if (u != v) { par[u] = v; } } int main() { ios::sync_with_stdio(false); int n, A, B; cin >> n >> A >> B; for (int i = 0; i < n; ++i) par[i] = i; for (int i = 0; i < n; ++i) { cin >> p[i].l >> p[i].r >> p[i].visible; } queue<Node> que; que.push(Node(A, B, 0)); while (!que.empty()) { int u = que.front().a, v = que.front().b, step = que.front().step; que.pop(); if (find(u) == find(v)) continue; if (p[u].visible != p[v].visible) { cout << step << endl; return 0; } merge(u, v); que.push(Node(p[u].l, p[v].l, step + 1)); que.push(Node(p[u].r, p[v].r, step + 1)); } cout << "indistinguishable\n"; }
F.
二分答案,所有获益的方案统计进入利润
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long LL; 4 const int N=1e5+10; 5 int n,m,a[N],b[N]; 6 bool ck(LL x){ 7 LL tmp=0; 8 for(int i=1;i<=n;i++){ 9 if(1ll*a[i]*x-1ll*b[i]>0)tmp+=1ll*a[i]*x-b[i]; 10 if(tmp>=m)return 1; 11 } 12 return tmp>=m; 13 } 14 int main(){ 15 scanf("%d%d",&n,&m); 16 for(int i=1;i<=n;i++) 17 scanf("%d%d",&a[i],&b[i]); 18 LL L=1,R=3e9,ans; 19 while(L<=R){ 20 LL mid=(L+R)>>1; 21 if(ck(mid))ans=mid,R=mid-1; 22 else L=mid+1; 23 } 24 cout<<ans; 25 }
G.
枚举ABC分别占据哪一段圆环即可
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=2e5+10; 4 char s[N]; 5 int numa[N],numb[N],numc[N],a,b,c,n,ans=1e7; 6 int getans(int pa,int pb,int pc){ 7 int res=0; 8 res+=a-(numa[pa+a-1]-numa[pa-1]); 9 res+=b-(numb[pb+b-1]-numb[pb-1]); 10 res+=c-(numc[pc+c-1]-numc[pc-1]); 11 return res; 12 } 13 int main(){ 14 scanf("%d",&n); 15 scanf("%s",s+1); 16 for(int i=n+1;i<=n*2;i++)s[i]=s[i-n]; 17 for(int i=1;i<=n*2;i++){ 18 numa[i]=numa[i-1]+(s[i]=='A'); 19 numb[i]=numb[i-1]+(s[i]=='B'); 20 numc[i]=numc[i-1]+(s[i]=='C'); 21 } 22 a=numa[n],b=numb[n],c=numc[n]; 23 for(int i=1;i<=n;i++){ 24 ans=min(ans,getans(i,i+a,i+a+b)); 25 ans=min(ans,getans(i,i+a+c,i+a)); 26 } 27 printf("%d\n",ans); 28 }
I.
二分答案+最大流
注意二分答案之后把图上的点按照可达性分成$2^{s}$个本质不同的块,每个块缩成一个点
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=2e5+10; 4 typedef long long LL; 5 const LL inf=2e18; 6 typedef pair<LL,int>pa; 7 int n,m,s,num[N],iter[N],ss,tt; 8 int bk[N],tot,first[N],siz[20],pos[20],dep[N]; 9 LL dis[11][N],sm,p[1<<11]; 10 inline int read(){ 11 int t=1,k=0;char c=getchar(); 12 while(c>'9'||c<'0'){if(c=='-')t=-1;c=getchar();} 13 while(c>='0'&&c<='9'){k=k*10+c-'0';c=getchar();} 14 return t*k; 15 } 16 struct edge{ 17 int to,next; 18 LL c; 19 }e[N*4]; 20 void add(int u,int v,LL d){ 21 e[++tot].next=first[u],first[u]=tot; 22 e[tot].c=d,e[tot].to=v; 23 } 24 void spfa(int x){ 25 dis[x][pos[x]]=0; 26 queue<int>q;q.push(pos[x]); 27 while(!q.empty()){ 28 int now=q.front();q.pop(); 29 for(int i=first[now];i;i=e[i].next){ 30 int u=e[i].to; 31 if(dis[x][u]>dis[x][now]+e[i].c){ 32 dis[x][u]=dis[x][now]+e[i].c; 33 if(!bk[u])bk[u]=1,q.push(u); 34 } 35 } 36 bk[now]=0; 37 } 38 } 39 int bfs(){ 40 memset(dep,-1,sizeof(dep)); 41 queue<int>q; 42 while(!q.empty())q.pop(); 43 dep[ss]=0;q.push(ss); 44 while(!q.empty()){ 45 int now=q.front();q.pop(); 46 for(int i=first[now];i;i=e[i].next){ 47 if(e[i].c<=0)continue; 48 int u=e[i].to; 49 if(dep[u]==-1)dep[u]=dep[now]+1,q.push(u); 50 } 51 } 52 return dep[tt]!=-1; 53 } 54 LL dfs(int x,LL flow){ 55 LL f=flow; 56 if(x==tt)return f; 57 for(int &i=iter[x];i;i=e[i].next){ 58 int u=e[i].to; 59 if(e[i].c>0&&dep[u]==dep[x]+1){ 60 LL tmp=dfs(u,min(flow,e[i].c)); 61 e[i].c-=tmp;e[i^1].c+=tmp;flow-=tmp; 62 if(!flow)return f; 63 } 64 } 65 return f-flow; 66 } 67 LL dinic(){ 68 LL ret=0; 69 while(bfs()){ 70 LL f; 71 memcpy(iter,first,sizeof(iter)); 72 while((f=dfs(ss,inf))>0)ret+=f; 73 } 74 return ret; 75 } 76 bool ck(LL x){ 77 memset(e,0,sizeof(e)); 78 memset(first,0,sizeof(first)); 79 memset(iter,0,sizeof(iter)); 80 memset(p,0,sizeof(p)); 81 tot=1;ss=(1<<s)+11,tt=(1<<s)+12; 82 for(int i=1;i<=n;i++){ 83 int tmp=0; 84 for(int j=0;j<s;j++){ 85 if(dis[j+1][i]<=x)tmp|=(1<<j); 86 } 87 p[tmp]+=1ll*num[i]; 88 } 89 for(int i=0;i<(1<<s);i++) 90 add(ss,i,p[i]),add(i,ss,0); 91 for(int i=1;i<=s;i++) 92 add((1<<s)+i,tt,siz[i]),add(tt,(1<<s)+i,0); 93 for(int i=0;i<s;i++) 94 for(int j=0;j<(1<<s);j++) 95 if((1<<i)&j){ 96 add(j,i+(1<<s)+1,inf);add(i+(1<<s)+1,j,0); 97 } 98 return dinic()>=sm; 99 } 100 int main(){ 101 scanf("%d%d%d",&n,&m,&s); 102 for(int i=1;i<=n;i++) 103 scanf("%d",&num[i]),sm+=1ll*num[i]; 104 for(int i=1,u,v,w;i<=m;i++){ 105 u=read();v=read();w=read(); 106 add(u,v,w);add(v,u,w); 107 } 108 for(int i=1;i<=s;i++)scanf("%d%d",&pos[i],&siz[i]); 109 for(int i=1;i<=s;i++) 110 for(int j=1;j<=n;j++)dis[i][j]=1e18; 111 for(int i=1;i<=s;i++)spfa(i); 112 LL L=0,R=2e18,ans; 113 while(L<=R){ 114 LL mid=(L+R)>>1; 115 if(ck(mid))ans=mid,R=mid-1; 116 else L=mid+1; 117 } 118 printf("%lld\n",ans); 119 }
J.
最大四边形面积。直接套婆罗摩笈多公式
#include <bits/stdc++.h> using namespace std; int main() { ios::sync_with_stdio(false); int a, b, c, d; cin >> a >> b >> c >> d; double s = (a + b + c + d) / 2.0; double sum = sqrt((s - a) * (s - b) * (s - c) * (s - d)); cout << fixed << setprecision(9) << sum << endl; }

浙公网安备 33010602011771号