Codeforces Round #509 (Div. 2)(一堆模拟)

由于晚上有点事所以根本没看最后一题,有空再补上(ง •̀_•́)ง 


A. Heist

给定一个数N,一个正整数序列,最少增加多少数可以使其变为严格连续的正整数序列

ans=max\{a_i\}-min\{a_i\}+1-N

 


B. Buying a TV Set

给定一个比例\frac{x}{y},两个范围a,b,求\frac{a_1}{b_1}=\frac{x}{y}(a_1\leq a,b_1\leq b)的方案数

先得到x_1=x/gcd(x,y),y_1=y/gcd(x,y),即分子至多为x_1的多少倍,分母至多为y_1多少倍

两者求出取较小值即可


C. Coffee Break

给定N个正整数{a_i},一个界限D,构造尽最将\{a_i\}划分为尽可能少的子序列,每个子序列排序后相邻元素差值大于等于D

先用multiset进行存储,然后进行贪心,先选取未选取过的最小元素a_x,再寻找按顺序满足a_y \geq a_x+D的元素

选择一遍相当于划分一个子序列,则至多进行N次,时间复杂度为O(NlogN)


D. Glider

一个网格,可以从(x_0,H)(\forall x_0 \in N)出发,网格上有两种区域,一种是给定的从(x_1,h_1)->(x_1+1,h_1);和一般的(x_1,h_1)->(x_1+1,h_1-1).当走到x轴的x_2停止,求max\{x_2-x_0\}

可以看出,应该从给定区域的左边界出发较优,即有n种可能.而一次移动的距离应该为H+len,len为经过的给定区域的长度

如果对于出发点i,确定终点j(经过j区域,但没到下一个区域),len通过前缀和得到

pre[j]-pre[i-1],pre[i]表示前i个区域的总长

j的判断是通过(i,i+1)中间的一般区域的长度inv[i]进行维护,当一般距离len_1+inv[j] \geq Hbreak得到j,下一次在-inv[i]转移到(i+1)即可.

这个维护是线性的O(N)


E. Tree Reconstruction

一个规则p,删掉树上一条边后,得到两个子树最大结点的编号p.x_1,p.x_2,给定N,N-1(x_1,x_2)点对(即每条边删一次),判断与构造符合条件的树

可以发现,关键的结点是N,N-1,对于符合条件的情况(x_1,x_2)中必含有N,总共至少有一个N-1.

记录每个结点出现次数,对于没有出现过的结点,记为空闲结点,用一个队列Q存储

对于N-1,应该是一条链与N相连;而其余结点则是在N-1开花

花从1-N-2连边,空闲结点也从小到大加入,这里还需要判断空闲结点是否构成非法状态



A. Heist

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;

using LL = long long;
int N;
int A[1005];
int ans;

int main(){
  cin >> N;
  int i;
  for(i = 1; i <= N; i++) cin >> A[i];
  sort(A + 1, A + 1 + N);
  ans = A[N] - A[1] + 1 - N;
  cout << ans << endl;
  return 0;
}

B. Buying a TV Set

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;

using LL = long long;
LL a, b, x, y;
LL ans;
LL gcd(LL, LL);

int main(){
  cin >> a >> b >> x >> y;
  LL tmp1, tmp2, d;
  d = gcd(x, y), x /= d, y /= d;
  tmp1 = a / x, tmp2 = b / y;
  ans = min(tmp1, tmp2);
  cout << ans << endl;
  return 0;
}

LL gcd(LL x, LL y){
  return (!y) ? x : gcd(y, x % y);
}

C. Coffee Break

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <set>
using namespace std;

using LL = long long;
const int MAXN = 2e5 + 5;
int N, M, D;
struct node {
  int val, id;
} A[MAXN];
bool operator <(const node &a, const node &b){
  return a.val < b.val;
}
multiset<node> S;
int ans[MAXN];

int main(){
  ios::sync_with_stdio(false);
  int i;
  cin >> N >> M >> D;
  for(i = 1; i <= N; i++) cin >> A[i].val, A[i].id = i, S.insert(A[i]);
  i = 0;
  while(S.size()){
    i++;
    auto j = S.begin();
    while(j != S.end()){
      int tmp = (*j).val;
      ans[(*j).id] = i;
      S.erase(j);
      j = S.lower_bound(node{tmp + D + 1, 0});
    }
  }
  cout << i << endl;
  for(i = 1; i < N; i++) cout << ans[i] << " ";
  cout << ans[i] << endl;
  return 0;
}

D. Glider

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;

using LL = long long;
const int MAXN = 2e5 + 5;
int N, H;
struct node {
  int x1, x2;
} A[MAXN];
bool cmp(node, node);
int pre[MAXN], inv[MAXN];
int ans;

int main(){
  ios::sync_with_stdio(false);
  int i, j;
  cin >> N >> H;
  for(i = 1; i <= N; i++) cin >> A[i].x1 >> A[i].x2;
  sort(A + 1, A + 1 + N, cmp);
  for(i = 1; i <= N; i++) pre[i] = pre[i - 1] + A[i].x2 - A[i].x1;
  for(i = 1; i < N; i++) inv[i] = A[i + 1].x1 - A[i].x2;
  j = 1;
  int len = 0;
  for(i = 1; i <= N; i++){
    while(j < N){
      if(len + inv[j] >= H) break;
      len += inv[j];
      j++;
    }
    ans = max(ans, H + pre[j] - pre[i - 1]);
    //cout << i << " " << j << " " << len << endl;
    len -= inv[i];
  }
  cout << ans << endl;
  return 0;
}

bool cmp(node a, node b){
  return a.x1 < b.x1;
}

E. Tree Reconstruction

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <set>
#include <vector>
#include <queue>
#include <stack>
using namespace std;

int N;
struct node {
  int x, y;
} A[1005];
int cnt[1005];
bool linked[1005];
queue<int> Q;
set<int> E[1005];

int main(){
  cin >> N;
  int i, j, x, y;
  for(i = 1; i < N; i++){
    cin >> x >> y;
    if(x > y) swap(x, y);
    if(y != N || x == N){
      printf("NO\n");
      return 0;
    }
    A[i].x = x, A[i].y = y;
    cnt[x]++;
  }
  if(!cnt[N - 1]){
    printf("NO\n");
    return 0;
  }
  for(i = 1; i <= N - 2; i++)
    if(!cnt[i]) Q.push(i);
  for(i = 1; i <= N - 2; i++)
    if(cnt[i]) E[N - 1].insert(i), cnt[i]--;
  E[N].insert(N - 1), cnt[N - 1]--;
  for(i = 1; i <= N - 2; i++){
    j = N - 1;
    while(cnt[i]){
      auto tmp = Q.front(); Q.pop();
      if(i < tmp){
        printf("NO\n");
        return 0;
      }
      E[j].erase(E[j].find(i));
      E[j].insert(tmp);
      E[tmp].insert(i);
      j = tmp;
      cnt[i]--;
    }
  }
  j = N;
  while(cnt[N - 1]){
    auto tmp = Q.front(); Q.pop();
    E[j].erase(E[j].find(i));
    E[j].insert(tmp);
    E[tmp].insert(i);
    j = tmp;
    cnt[N - 1]--;
  }
  cout << "YES" << endl;
  for(i = 1; i <= N; i++)
    for(auto k:E[i])
      cout << i << " " << k << endl;
  return 0;
}

猜你喜欢

转载自blog.csdn.net/Hardict/article/details/82730536