Codeforces Round #532 (Div. 2)
Posted mountaink
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces Round #532 (Div. 2)相关的知识,希望对你有一定的参考价值。
题意:给出k,让你求b,使所有位置c(c满足$ c = b + i * k$) 的标签全部消失,使1和-1的数量相差最大,求b。
枚举。
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn=100010; int n,k; int aa,bb; int p; int v[110]; int main(){ while(cin>>n>>k) { p=1000*k; for(int i=1;i<=n;i++) { int u; cin>>v[i]; if(v[i]>0)aa++; else bb++; } int ans=0; for(int b=1;b<=n;b++) { int xx=aa,yy=bb; for(int j=b-1;j>0;j--) { if((b-j)%k==0) { if(v[j]>0)xx--; else yy--; } } for(int j=b;j<=n;j++) { if((j-b)%k==0) { if(v[j]>0)xx--; else yy--; } } ans=max(ans,abs(xx-yy)); } cout<<ans<<endl; } }
题意:依次给出数字,当凑足了1-n时输出1,否则输出0。
记录当前位置有几个数字了,凑满数字就所有vis(次数数组减一),一开始居然想到用线段树维护维护这个减一操作和查询次数,因为觉得n太大了每次都扫一遍会超时。后来发现,由于m时固定的,所以扫描n的次数最多是m/n次,每次要n的时间,所以就是o(m)的时间。所以暴力不会出事。
#include<bits/stdc++.h> #define CLR(a,b) memset(a,b,sizeof(a)) using namespace std; typedef long long ll; const int maxn=100010; int n,m; int a[maxn]; int vis[maxn]; string ans; int main(){ while(cin>>n>>m) { CLR(vis,0); ans=""; for(int i=1;i<=m;i++) { scanf("%d",&a[i]); } int tot=0; for(int i=1;i<=m;i++) { if(vis[a[i]]==0){ tot++; vis[a[i]]=1; }else{ vis[a[i]]++; } if(tot<n)ans+="0"; else{ ans+="1"; tot=0; for(int j=1;j<=n;j++) { vis[j]--; if(vis[j]>0)tot++; } } } cout<<ans<<endl; } }
C. NN and the Optical Illusion
初中计算几何题,设外半径为R,半径为r,可以列方程,会解二元一次方程就可以,直接套求根公式。
#include<bits/stdc++.h> #define CLR(a,b) memset(a,b,sizeof(a)) using namespace std; typedef long long ll; const int maxn=100010; const double pai=acos(-1.0); double n,r,R,p,die; int main(){ while(cin>>n>>r) { p=cos(2*pai/n); // cout<<p<<endl; die=(4*r*p-4*r)*(4*r*p-4*r)-4*(2+2*p)*(2*r*r*p-2*r*r); double ans=((4*r-4*r*p)+sqrt(die))/(4+4*p); printf("%.8f ",ans); } }
待补
题意:给出衣服有向图,每条边的权值是代表使这条边反向所需要的能力,现在希望使整幅图无环,并且只要使一条边反向了,其他所有权值小于等于这条边的边都可以免费反向。
题解:显然是一个可以二分的题目,因为对所有边进行合法操作必然能得到一个合法的图,这个limit越小则限制越严格。
对于一个二分出来的权值k,我们可以先把所有权值小于等于k的边全部取消,而其他边全部变成拓扑偏序关系,由于取消掉了这些边,所以这些边的影响相当于是最后由我决定的,只要我能写出合法的拓扑序列,那我按照这个拓扑序列来决定边的方向即可。合法的拓扑序列即拓扑完成后元素个数等于n(否则说明有环,元素还在队列里)。
不断二分k,那怎么根据拓扑序列来决定边的方向呢?其实就是看每个元素的拓扑序号是多少,比如u和v,如果u有一条连向v的有向边,但u的拓扑序号却比v的拓扑序号大,说明在拓扑序列中,u在v的后面,所以这条边要被反向,即输出。
#include<bits/stdc++.h> #define clr(a,b) memset(a,b,sizeof(a)) using namespace std; typedef long long ll; const int maxn=1e5+10; int n,m; struct node{ int u,v; ll w; }; struct edge{ int to,Next; }e[maxn]; vector<node >a; int u,v,tot,head[maxn],d[maxn],top[maxn]; ll w,l,r,mid; void addv(int u,int v){ e[++tot].to=v; e[tot].Next=head[u]; head[u]=tot; } bool toposort(){ queue<int >q; int cnt=0; for(int i=1;i<=n;i++) { if(d[i]==0){ q.push(i); } } while(!q.empty()) { int u=q.front(); top[u]=++cnt; q.pop(); for(int i=head[u];i!=-1;i=e[i].Next) { int v=e[i].to; d[v]--; if(d[v]==0) { q.push(v); } } } if(cnt==n)return true; return false; } void buildGraph(ll mid){ clr(head,-1),tot=0; clr(d,0); for(int i=0;i<m;i++) { int st=a[i].u,ed=a[i].v; ll val=a[i].w; if(val>mid){ addv(st,ed); d[ed]++; } } } vector<int >ans; int main(){ while(cin>>n>>m) { a.clear(); ans.clear(); l=0,r=0; for(int i=0;i<m;i++) { scanf("%d%d%lld",&u,&v,&w); a.push_back({u,v,w}); r=max(r,w); } while(l<r) { mid=(l+r)>>1; buildGraph(mid); if(toposort()){ r=mid; }else { l=mid+1; } } buildGraph(r); toposort(); for(int i=0;i<m;i++) { if(a[i].w<=r && top[a[i].u]>top[a[i].v])ans.push_back(i+1); } int si=ans.size(); printf("%lld %d ",r,si); for(int i=0;i<si;i++) { printf("%d%c",ans[i]," "[i==si-1]); } } }
待补。
以上是关于Codeforces Round #532 (Div. 2)的主要内容,如果未能解决你的问题,请参考以下文章
Codeforces Round #436 E. Fire(背包dp+输出路径)
[ACM]Codeforces Round #534 (Div. 2)
Codeforces Round #726 (Div. 2) B. Bad Boy(贪心)