Educational Codeforces Round 2

600A - Extract Numbers    20171106

字符串处理题,稍微注意点细节就能水过

#include<stdlib.h>
#include<stdio.h>
#include<math.h>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
string s;int _;
vector<string>a,b;
void check(int l,int r)
{
    if(l==r){b.push_back("");return;}
    if(l==r-1)
      {
      if(s[l]>='0' && s[l]<='9')
        a.push_back(""),a[a.size()-1].assign(s,l,r-l);
      else b.push_back(""),b[b.size()-1].assign(s,l,r-l);
      return;
      }
    if(s[l]=='0'){b.push_back(""),b[b.size()-1].assign(s,l,r-l);return;}
    for(int i=l;i<r;i++)
      if(s[i]<'0' || s[i]>'9')
        {
        b.push_back("");
        b[b.size()-1].assign(s,l,r-l);
        return;
        }
    a.push_back("");
    a[a.size()-1].assign(s,l,r-l);
}
int main()
{
    cin>>s;
    for(int i=0;i<s.size();i++)
      if(s[i]==',' || s[i]==';')
        check(_,i),_=i+1;check(_,s.size());
    if(a.size()==0)printf("-\n");else{cout<<char(34);
    for(int i=0;i<a.size();i++)
      {cout<<a[i];printf("%c",i==a.size()-1?'"':',');}cout<<endl;}
    if(b.size()==0)printf("-\n");else{cout<<char(34);
    for(int i=0;i<b.size();i++)
      {cout<<b[i];printf("%c",i==b.size()-1?'"':',');}cout<<endl;}
    return 0;
}
View Code

 

600B - Queries about less or equal elements    20171106

对a数组排序后upperbound一下就好了,当然想手写二分也不拦着╮(╯▽╰)╭

#include<stdlib.h>
#include<stdio.h>
#include<math.h>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int n,m,x;
int a[200001];
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
      scanf("%d",&a[i]);
    sort(a+1,a+n+1);
    for(int i=1;i<=m;i++)
      {scanf("%d",&x);cout<<upper_bound(a+1,a+n+1,x)-a-1<<endl;}
    return 0;
}
View Code

 

600C - Make Palindrome    20171106

由于可以改变排列顺序,所以尽可能地把大的出现次数为奇数的字母改为小的出现次数为奇数的字母一定是最优的

#include<stdlib.h>
#include<stdio.h>
#include<math.h>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int pos[26],sum[26],l,r;
string s;
int main()
{
    cin>>s;
    for(int i=0;i<s.size();i++)
      pos[s[i]-'a']=i,sum[s[i]-'a']++;
    int mid=-1;l=0,r=25;
    while(l<r)
      {
      while(sum[l]%2==0 && l<26)l++;
      while(sum[r]%2==0 && r>=0)r--;
      if(l>=r)break;
      s[pos[r]]=l+'a';
      sum[l++]++,sum[r--]--;
      }
    for(int i=0;i<26;i++)
      if(sum[i]&1)mid=i;
    sort(s.begin(),s.end());
    for(int i=0;i<s.size();i+=2)
      {
      if(s[i]==mid+'a' && i%2==0)i++;
      if(i<s.size())cout<<s[i];
      }
    if(mid!=-1)cout<<char(mid+'a');
    for(int i=s.size()-1;i>=0;i-=2)
      {
      if(s[i]==mid+'a')i--,mid=-1;
      if(i>=0)cout<<s[i];
      }
    cout<<endl;return 0;
}
View Code

 

600D - Area of Two Circles' Intersection    20171111 20180831

一道计算几何模板题,当年没有模板的时候被卡精度卡成SB,结果发现把输出小数位数减少到6位就过了...前两天测试学长模板的时候直接秒掉了【论模板的重要性】

附上当年蠢得一比的代码

#include<stdlib.h>
#include<stdio.h>
#include<math.h>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const long double pi=acos(-1.0);
struct Circle{long double x,y,r;}c1,c2;
double ans;
void print(){printf("%.6lf\n",ans);}
int main()
{
    cin>>c1.x>>c1.y>>c1.r>>c2.x>>c2.y>>c2.r;
    long double dis=pow(pow(c1.x-c2.x,2)+pow(c1.y-c2.y,2),0.5);
    if(c1.r+c2.r<=dis)return ans=0,print(),0;
    if(c1.r-c2.r>=dis)return ans=pi*c2.r*c2.r,print(),0;
    if(c2.r-c1.r>=dis)return ans=pi*c1.r*c1.r,print(),0;
    long double angle1=2*acos((c1.r*c1.r+dis*dis-c2.r*c2.r)/(2*dis*c1.r));
    long double angle2=2*acos((c2.r*c2.r+dis*dis-c1.r*c1.r)/(2*dis*c2.r));
    long double s1=c1.r*c1.r*angle1/2,s2=c2.r*c2.r*angle2/2;
    long double t1=sin(angle1)*c1.r*c1.r/2,t2=sin(angle2)*c2.r*c2.r/2;
    ans=s1-t1+s2-t2,print();
    return 0;
}
View Code

 

600E - Lomsat gelral    20180902

启发式合并,和Codeforces 375D的做法类似,直接套用了之前的代码魔改一下就过了_(:з」∠)_

#include<bits/stdc++.h>
using namespace std;
#define N 100001
#define LL long long
LL ans[N];
int n,x,y,c[N];
vector<int>d[N];
map<int,LL>cnt[N],f[N];
void dfs(int cur,int pre)
{
    cnt[cur][c[cur]]=1,f[cur][1]=c[cur];
    for(auto nxt:d[cur])if(nxt!=pre)
      {
      dfs(nxt,cur);
      if(cnt[nxt].size()>cnt[cur].size())
        cnt[cur].swap(cnt[nxt]),f[cur].swap(f[nxt]);
      for(auto x:cnt[nxt])
        {
        int y=cnt[cur][x.first];
        cnt[cur][x.first]+=x.second;
        for(int i=y+1;i<=y+x.second;i++)
          f[cur][i]+=x.first;
        }
      }
    ans[cur]=(*f[cur].rbegin()).second;
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
      scanf("%d",&c[i]);
    for(int i=2;i<=n;i++)
      scanf("%d%d",&x,&y),
      d[x].push_back(y),
      d[y].push_back(x);
    dfs(1,0);
    for(LL i=1;i<=n;i++)
      printf("%I64d%c",ans[i],i<n?' ':'\n');
    return 0;
}
View Code

 

600F - Edge coloring of bipartite graph    20180902

显然颜色种数是各顶点度数的最大值,下面给出一种构造方法

每次读入一条边时,分别查找该边的两顶点 u,v 的第一个未被用过的颜色,设其为c1,c2 。若c1==c2,则直接染色,否则由于v这边c1已经被占用,我们需要查找到与v共享颜色c1的点w,并将v与w之间的边改为颜色c2,这样u与v之间就可以连上一条颜色为c1的边了。在改边[v,w]的颜色时,也可能会出现w这边c2已经被占用的情况,这时就需要递归进行操作(类似于匈牙利算法的做法)。显然这样做的复杂度最大是O(n),那么整个程序的时间复杂度就是O(mn)

#include<bits/stdc++.h>
using namespace std;
#define N 2001
#define M 100001
struct rua{int v,id;};
int a,b,m,u,v,ans,x[N][N],f[N][N],c[M];
void dfs(int u,int v,int c1,int c2)
{
    int w=x[v][c1];
    x[v][c1]=u,x[u][c1]=v;
    if(w)dfs(v,w,c2,c1);
    else x[v][c2]=0;
}
int main()
{
    scanf("%d%d%d",&a,&b,&m);
    for(int i=1;i<=m;i++)
      {
      scanf("%d%d",&u,&v),v+=a;
      f[u][v]=f[v][u]=i;
      int c1=1,c2=1;
      while(x[u][c1])c1++;
      while(x[v][c2])c2++;
      if(c1==c2)x[u][c1]=v,x[v][c2]=u;
      else dfs(u,v,c1,c2);
      ans=max(ans,max(c1,c2));
      }
    for(int i=1;i<=a;i++)
      for(int j=1;j<=ans;j++)
        if(x[i][j])c[f[i][x[i][j]]]=j;
    printf("%d\n",ans);
    for(int i=1;i<=m;i++)
      printf("%d%c",c[i],i<m?' ':'\n');
    return 0;
}
View Code

 

posted @ 2018-09-02 16:20  DeaphetS  阅读(130)  评论(0编辑  收藏  举报