静かで孤独な日記

のんびりたまに

ABC033 D 三角形の分類

using namespace std;
//const ll MOD=(ll)1e9+7;
//const ll inf=(ll)1e14;
const double PI=acos(-1.0);
const double EPS=1e-10;
const int dy[]={1,0,-1};
const int dx[]={1,0,-1};
int n,m,h,w;
string s;
ll x[2001],y[2001];

int main(){
  ios::sync_with_stdio(false);
  cin.tie(0);
  cout.precision(10);
  cout<<fixed;
#ifdef LOCAL_DEFINE
  FILE *stream1;
  //FILE *stream2;
  stream1=freopen("in","r",stdin);
  //stream2=freopen("out","w",stdout);
  if(stream1==NULL)return 0;
  //if(stream2==NULL)return 0;
#endif
  cin>>n;
  for(int i=0;i<n;i++){
    cin>>x[i]>>y[i];
  }
  ll ans1=0,ans2=0,ans3=0;
  for(int i=0;i<n;i++){
    vector<double> v;
    for(int j=0;j<n;j++){
      if(i==j)continue;
      v.push_back(atan2(y[j]-y[i],x[j]-x[i]));
    }
    sort(v.begin(),v.end());
    for(int j=0;j<n-1;j++){
      v.push_back(v[j]+2*PI);
    }
    for(int j=0;j<n-1;j++){
      int a=lower_bound(v.begin(),v.end(),v[j]+PI/2-EPS)-v.begin();
      int b=upper_bound(v.begin(),v.end(),v[j]+PI/2+EPS)-v.begin();
      int c=lower_bound(v.begin(),v.end(),v[j]+PI)-v.begin();
      ans2+=b-a;
      ans3+=c-b;
    }
  }
  ans1=(ll)n*(n-1)*(n-2)/6-ans2-ans3;
  print(ans1,ans2,ans3);
#ifdef LOCAL_DEFINE
  cerr<<"Time elapsed: "<<1.0*clock()/CLOCKS_PER_SEC<<"s.\n";
  fclose(stream1);
  //fclose(stream2);
#endif
  return 0;
}

  • 2種類求めて全体から2種類分引いて残りを求めるのはわかるけど、慣れてないのもあって手が出なかった。
  • 角度で持ってあげるのいいね。
  • あとEPSの使い方がわからなかったので少し戸惑った(写真)

ABC049 D 連結

using namespace std;
//const ll MOD=(ll)1e9+7;
//const ll inf=(ll)1e14;
const int dy[]={1,0,-1};
const int dx[]={1,0,-1};
int n,m,h,w;
string s;
int k,l;

class union_find{
public:
    explicit union_find(int _n):n(_n){
        par.resize(static_cast<unsigned long>(_n));
        rank.resize(static_cast<unsigned long>(_n));
        sizes.resize(static_cast<unsigned long>(_n));
        for(int i=0;i<_n;i++){
            par[i]=i;
            rank[i]=0;
            sizes[i]=1;
        }
    }
    int find(int a){
        if(par[a]==a)return a;
        return par[a]=find(par[a]);
    }
    bool same(int a,int b){
        return find(a)==find(b);
    }
    void unite(int a,int b){
        link(find(a),find(b));
    }
    int size(int a){
        return sizes[find(a)];
    }
    void view(){
        for(int i=0;i<n;i++){
            cout<<" par"<<"["<<i<<"]="<<par[i]<<((i==n-1)?"\n":",");
        }
        for(int i=0;i<n;i++){
            cout<<"size"<<"["<<i<<"]="<<sizes[i]<<((i==n-1)?"\n":",");
        }
        cout<<endl;
    }

private:
    void link(int a,int b){
        if(same(a,b))return;
        if(rank[a]>rank[b]){
            par[b]=a;
            sizes[a]+=sizes[b];
            //sizes[b]=0;
        }else{
            par[a]=b;
            if(rank[a]==rank[b])rank[b]++;
            sizes[b]+=sizes[a];
            //sizes[a]=0;
        }
    }
    int n;
    vector<int> par;
    vector<int> rank;
    vector<int> sizes;
};

int ans[100001];
map<pair<int,int> ,int> mp;

int main(){
  ios::sync_with_stdio(false);
  cin.tie(0);
  cout.precision(10);
  cout<<fixed;
#ifdef LOCAL_DEFINE
  FILE *stream1;
  //FILE *stream2;
  stream1=freopen("in","r",stdin);
  //stream2=freopen("out","w",stdout);
  if(stream1==NULL)return 0;
  //if(stream2==NULL)return 0;
#endif
  cin>>n>>k>>l;
  union_find uf1(n);
  for(int i=0;i<k;i++){
    int a,b;cin>>a>>b;
    a--;b--;
    uf1.unite(a,b);
  }
  union_find uf2(n);
  for(int i=0;i<l;i++){
    int a,b;cin>>a>>b;
    a--;b--;
    uf2.unite(a,b);
  }
  for(int i=0;i<n;i++){
    mp[make_pair(uf1.find(i),uf2.find(i))]++;
  }
  for(int i=0;i<n;i++){
    if(i==n-1){
      cout<<mp[make_pair(uf1.find(i),uf2.find(i))]<<endl;
    }else{
      cout<<mp[make_pair(uf1.find(i),uf2.find(i))]<<" ";
    }
  }
#ifdef LOCAL_DEFINE
  cerr<<"Time elapsed: "<<1.0*clock()/CLOCKS_PER_SEC<<"s.\n";
  fclose(stream1);
  //fclose(stream2);
#endif
  return 0;
}
  • uf使う感じするよね。
  • でも答えの求め方がわかんなかった。
  • それぞれのufで同じグループだったらオッケーなのを思いつきたかったなぁ。

ABC030-D へんてこ辞書

using namespace std;
//const ll MOD=(ll)1e9+7;
//const ll inf=(ll)1e14;
int n,a;
string k;
int b[100001];
int num[100001];

int main(){
  ios::sync_with_stdio(false);
  cin.tie(0);
  cout.precision(10);
  cout<<fixed;
#ifdef LOCAL_DEFINE
  FILE *stream1;
  //FILE *stream2;
  stream1=freopen("in","r",stdin);
  //stream2=freopen("out","w",stdout);
  if(stream1==NULL)return 0;
  //if(stream2==NULL)return 0;
#endif
  cin>>n>>a;a--;
  cin>>k;
  for(int i=0;i<n;i++){
    cin>>b[i];b[i]--;
  }
  if((int)k.size()<=7){
    ll h=stoi(k);
    int ans=a;
    for(int i=0;i<h;i++){
      ans=b[ans];
    }
    print(ans+1);
  }else{
    for(int i=0;i<n;i++){
      num[i]=-1;
    }
    int now=a;
    int t,circle;
    for(int i=0;;i++){
      if(num[now]!=-1){
        t=num[now];
        circle=i-t;
        break;
      }
      num[now]=i;
      now=b[now];
    }
    int h=0;
    for(int i=0;i<(int)k.size();i++){
      h=(h*10+(int)(k[i]-'0'))%circle;
    }
    h-=t;
    if(h<0){
      int temp=-h/circle;
      temp++;
      h+=circle*temp;
    }
    int ans=a;
    for(int i=0;i<t+h;i++){
      ans=b[ans];
    }
    print(ans+1);
  }
#ifdef LOCAL_DEFINE
  cerr<<"Time elapsed: "<<1.0*clock()/CLOCKS_PER_SEC<<"s.\n";
  fclose(stream1);
  //fclose(stream2);
#endif
  return 0;
}

  • 最初、ダブリングだーって思って提出したらWAで、なんでやって制約見たら卒倒した。
  • 閉路に入る前と後に分けるのが重要で、modとった後に閉路に入る前の分だけ引く。
  • これでマイナスだとダメなので正の数に直してあげましょう。

ABC031-D 語呂合わせ

using namespace std;
//const ll MOD=(ll)1e9+7;
//const ll inf=(ll)1e14;
int n,k;
string v[51],w[51];
int mojisuu[10];

bool check(){
  map<char,string> mp;
  for(int i=0;i<n;i++){
    int nowmojisuu=0;
    for(int j=0;j<(int)v[i].size();j++){
      nowmojisuu+=mojisuu[v[i][j]-'0'];
    }
    if(nowmojisuu!=(int)w[i].size())return 0;
    int start=0;
    for(int j=0;j<(int)v[i].size();j++){
      if(mp.count(v[i][j])){
        string temp="";
        for(int k=0;k<(int)mp[v[i][j]].size();k++)temp+=mp[v[i][j]][k];
        string temp2=w[i].substr(start,mojisuu[v[i][j]-'0']);
        if(temp!=temp2)return 0;
        else{
          start+=mojisuu[v[i][j]-'0'];
        }
        continue;
      }
      mp[v[i][j]]=w[i].substr(start,mojisuu[v[i][j]-'0']);
      start+=mojisuu[v[i][j]-'0'];
    }
  }
  for(int i=0;i<n;i++){
    string now="";
    for(int j=0;j<(int)v[i].size();j++){
      now+=mp[v[i][j]];
    }
    if(now!=w[i])return 0;
  }
  for(int i=0;i<k;i++){
    cout<<mp[(char)(i+'1')]<<"\n";
  }
  return 1;
}

void dfs(int nownum,int nowmojisuu){
  mojisuu[nownum]=nowmojisuu;
  if(nownum==k){
    if(check())exit(0);
  }else{
    for(int i=1;i<=3;i++){
      dfs(nownum+1,i);
    }
  }
}

int main(){
  ios::sync_with_stdio(false);
  cin.tie(0);
  cout.precision(10);
  cout<<fixed;
#ifdef LOCAL_DEFINE
  FILE *stream1;
  //FILE *stream2;
  stream1=freopen("in","r",stdin);
  //stream2=freopen("out","w",stdout);
  if(stream1==NULL)return 0;
  //if(stream2==NULL)return 0;
#endif
  cin>>k>>n;
  for(int i=0;i<n;i++){
    cin>>v[i]>>w[i];
  }
  for(int i=1;i<=3;i++){
    dfs(1,i);
  }
#ifdef LOCAL_DEFINE
  cerr<<"Time elapsed: "<<1.0*clock()/CLOCKS_PER_SEC<<"s.\n";
  fclose(stream1);
  //fclose(stream2);
#endif
  return 0;
}
  • めっちゃめんどくさかった。。。

ABC027-D ロボット

using namespace std;
//const ll MOD=(ll)1e9+7;
//const ll inf=(ll)1e14;
const int dy[]={1,0,-1};
const int dx[]={1,0,-1};
int n,m,h,w;
string s;

int main(){
  ios::sync_with_stdio(false);
  cin.tie(0);
  cout.precision(10);
  cout<<fixed;
#ifdef LOCAL_DEFINE
  FILE *stream1;
  //FILE *stream2;
  stream1=freopen("in","r",stdin);
  //stream2=freopen("out","w",stdout);
  if(stream1==NULL)return 0;
  //if(stream2==NULL)return 0;
#endif
  cin>>s;
  n=(int)s.size();
  int now=0;
  vector<int> v;
  for(int i=n-1;i>=0;i--){
    if(s[i]=='+'){
      now++;
    }else if(s[i]=='-'){
      now--;
    }else{
      v.push_back(now);
    }
  }
  sort(v.begin(),v.end());
  int ans=0;
  for(int i=0;i<(int)v.size();i++){
    if(i<(int)v.size()/2){
      ans+=-v[i];
    }else ans+=v[i];
  }
  print(ans);
#ifdef LOCAL_DEFINE
  cerr<<"Time elapsed: "<<1.0*clock()/CLOCKS_PER_SEC<<"s.\n";
  fclose(stream1);
  //fclose(stream2);
#endif
  return 0;
}
  • 僕は入力される+と-にしか注目できませんでした。
  • 視点を変えて、Mに注目すると見えるんですね。

ABC026-D 高橋君ボール1号

using namespace std;
//const ll MOD=(ll)1e9+7;
//const ll inf=(ll)1e14;
const int dy[]={1,0,-1};
const int dx[]={1,0,-1};
const double eps=1e-10;
int n,m,h,w;
string s;
double a,b,c;
const double PI=acos(-1.0);

bool check(double mid){
  double f_t=a*mid+b*sin(c*mid*PI);
  if(f_t>100+eps){
    return 1;
  }else return 0;
}

int main(){
  ios::sync_with_stdio(false);
  cin.tie(0);
  cout.precision(10);
  cout<<fixed;
#ifdef LOCAL_DEFINE
  FILE *stream1;
  //FILE *stream2;
  stream1=freopen("in","r",stdin);
  //stream2=freopen("out","w",stdout);
  if(stream1==NULL)return 0;
  //if(stream2==NULL)return 0;
#endif
  cin>>a>>b>>c;
  double l=0,r;
  for(int i=1;;i++){
    if(a*(double)i+b*sin(c*(double)i*PI)>100+eps){
      r=i;
      l=i-1;
      break;
    }
  }
  for(int i=0;i<100;i++){
    double mid=(l+r)/2;
    if(check(mid)){
      r=mid;
    }else{
      l=mid;
    }
  }
  print(l);
#ifdef LOCAL_DEFINE
  cerr<<"Time elapsed: "<<1.0*clock()/CLOCKS_PER_SEC<<"s.\n";
  fclose(stream1);
  //fclose(stream2);
#endif
  return 0;
}
  • こんなのも二分探索でいけるんですね。

ARC092-D Two Sequences

using namespace std;
//const ll MOD=(ll)1e9+7;
//const ll inf=(ll)1e14;
const int dy[]={1,0,-1};
const int dx[]={1,0,-1};
int n,m,h,w;
string s;
ll a[200001],b[200001];

int main(){
  ios::sync_with_stdio(false);
  cin.tie(0);
  cout.precision(10);
  cout<<fixed;
#ifdef LOCAL_DEFINE
  FILE *stream1;
  //FILE *stream2;
  stream1=freopen("in","r",stdin);
  //stream2=freopen("out","w",stdout);
  if(stream1==NULL)return 0;
  //if(stream2==NULL)return 0;
#endif
  cin>>n;
  for(int i=0;i<n;i++){
    cin>>a[i];
  }
  for(int i=0;i<n;i++){
    cin>>b[i];
  }
  ll t=1;
  ll ans=0;
  for(int i=0;i<30;i++){
    if(i!=0)t*=2;
    vector<int> v1,v2;
    for(int j=0;j<n;j++){
      v1.push_back(a[j]%(2*t));
      v2.push_back(b[j]%(2*t));
    }
    sort(v2.begin(),v2.end());
    int res=0;
    for(int j=0;j<n;j++){
      int x=lower_bound(v2.begin(),v2.end(),t-v1[j])-v2.begin();
      int y=lower_bound(v2.begin(),v2.end(),2*t-v1[j])-v2.begin();
      int z=lower_bound(v2.begin(),v2.end(),3*t-v1[j])-v2.begin();
      res+=y-x;
      res+=n-z;
    }
    if(res&1){
      ans+=t;
    }
  }
  print(ans);
#ifdef LOCAL_DEFINE
  cerr<<"Time elapsed: "<<1.0*clock()/CLOCKS_PER_SEC<<"s.\n";
  fclose(stream1);
  //fclose(stream2);
#endif
  return 0;
}
  • 解説動画見て実装
  • なんかむちゃくちゃ遅かった
  • k- bit目が1か0かが周期的であることに気づけなかった
  • xorを考えるときは各 bitごとに区切って考えるのが定石だそうです(ツイッターで誰かが言ってました)