• Hello2020(前四题题解)


    Hello2020(前四题题解)

    Hello,2020!新的一年从快乐的掉分开始……

    我在m3.codeforces.com这个镜像网站中一开始还打不开D题,我……

    还有话说今天这场为什么那么多二分。

    比赛传送门:https://codeforces.com/contest/1284

    A. New Year and Naming

    题目大意:这题就是一个干支纪年法。每年的名字分两段,第一段在n个字符串中取,第二段在m个字符串中取,每过一年就各取下一个,如果取到n(m)就去取第一个。

    纯模拟,加上一点点字符串操作。

    又丑又长的代码:

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <algorithm>
     4 #include <cstring>
     5 #include <vector>
     6 #define rep(x, l, r) for(int x = l; x <= r; x++)
     7 #define repd(x, r, l) for(int x = r; x >= l; x--)
     8 #define clr(x, y) memset(x, y, sizeof(x))
     9 #define all(x) x.begin(), x.end()
    10 #define pb push_back
    11 #define mp make_pair
    12 #define MAXN 2005
    13 #define fi first
    14 #define se second
    15 #define SZ(x) ((int)x.size())
    16 using namespace std;
    17 typedef long long ll;
    18 typedef vector<int> vi;
    19 typedef pair<int, int> pii;
    20 const int INF = 1 << 30;
    21 const int p = 1000000009;
    22 int lowbit(int x){ return x & (-x);}
    23 int fast_power(int a, int b){ int x; for(x = 1; b; b >>= 1){ if(b & 1) x = 1ll * x * a % p; a = 1ll * a * a % p;} return x % p;}
    24 
    25 char st1[MAXN][25], st2[MAXN][25];
    26 
    27 int main(){
    28     int n, m;
    29     scanf("%d%d", &n, &m);
    30     rep(i, 1, n) scanf("%s", st1[i]);
    31     rep(i, 1, m) scanf("%s", st2[i]);
    32     int q;
    33     scanf("%d", &q);
    34     rep(i, 1, q){
    35         int x;
    36         scanf("%d", &x);
    37         int len = strlen(st1[(x - 1) % n + 1]);
    38         rep(j, 0, len - 1) putchar(st1[(x - 1) % n + 1][j]);
    39         puts(st2[(x - 1) % m + 1]);
    40     }
    41     return 0;
    42 }
    View Code-A

    B.New Year and Ascent Sequence

    题目大意:给你n个序列,每次取任意两个序列(可以取同一个,并且交换前后顺序算不同种)接起来(比如说‘11’和‘22’就是‘1122’)。问这n2个接成序列中共有多少个序列中存在顺序对。

    不难看出,如果一个序列中本身存在顺序对,接成的序列也肯定存在顺序对。

    判断方法

    if(x > minx) flag = 1;
    

     将它们找出来后直接统计入答案,套上一个小学学的容斥原理

    ans = 1ll * 2 * cnt1 * n - 1ll * cnt1 * cnt1;
    

     然后主要问题就是这些剩下的没有顺序对的序列。

    很显然凡是最大值比这个序列最小值大的,就可以和这个序列接起来。

    将最大值排序后二分一下最小的最大值就好。

    代码如下

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <algorithm>
     4 #include <cstring>
     5 #include <vector>
     6 #define rep(x, l, r) for(int x = l; x <= r; x++)
     7 #define repd(x, r, l) for(int x = r; x >= l; x--)
     8 #define clr(x, y) memset(x, y, sizeof(x))
     9 #define all(x) x.begin(), x.end()
    10 #define pb push_back
    11 #define mp make_pair
    12 #define MAXN 100005
    13 #define fi first
    14 #define se second
    15 #define SZ(x) ((int)x.size())
    16 using namespace std;
    17 typedef long long ll;
    18 typedef vector<int> vi;
    19 typedef pair<int, int> pii;
    20 const int INF = 1 << 30;
    21 const int p = 1000000009;
    22 int lowbit(int x){ return x & (-x);}
    23 int fast_power(int a, int b){ int x; for(x = 1; b; b >>= 1){ if(b & 1) x = 1ll * x * a % p; a = 1ll * a * a % p;} return x % p;}
    24 
    25 vi a, b;
    26 
    27 int main(){
    28     int n;
    29     scanf("%d", &n);
    30     int cnt1 = 0, cnt2 = 0;
    31     rep(i, 1, n){
    32         int k;
    33         scanf("%d", &k);
    34         int minx = INF, maxx = -INF;
    35         bool flag = 0;
    36         rep(j, 1, k){
    37             int x;
    38             scanf("%d", &x);
    39             if(x > minx) flag = 1;
    40             minx = min(minx, x);
    41             maxx = max(maxx, x);
    42         }
    43         if(flag) cnt1++;
    44         else{
    45             cnt2++;
    46             a.pb(minx);
    47             b.pb(maxx);
    48         }
    49     }    
    50     sort(all(b));
    51     ll ans = 1ll * 2 * cnt1 * n - 1ll * cnt1 * cnt1;
    52     rep(i, 0, SZ(b) - 1){
    53         ans += cnt2 - (upper_bound(all(b), a[i]) - b.begin());
    54     }
    55     printf("%I64d
    ", ans);
    56     return 0;
    57 }
    View Code-B

    C.New Year and Permutation

    题目大意:在所有由[1,n]组成的排列中,有多少对数(l,r)满足max{pl,pl+1,…,pr} - min{pl,pl+1,…,pr} = r - l。

    似乎解释的不是很清楚,再来个样例解释一下。

    当n = 3时,所有的排列为[1,23],[1,32],[213],[231],[312],[321]。

    对于[123]:(1,1)中max = 1, min = 1, r - l = 0,成立;(1,3)中max = 3, min = 1, r - l = 2,成立。

    对于[1,3,2]:(1,2)中max = 3, min = 1, r - l = 1,不成立。

    别的懒得说了,原题样例说明有。

    这道题一开始看的时候有点慌,浪费了好多时间。

    后来一想,不就分别统计长度为i的子段满足条件。

    我们可以很轻松的求出不同子段出现次数,所有该长度的子段出现次数为:

    排列个数×每个排列中出现的次数 = n!×(n - i +1)

    然后该长度不同子段的个数为n!/ (n - i)!,稍微证明一下或者列举几个便可以得出。

    然后求所有符合条件的字段个数,(1,2,…,i ) 到(n - i + 1,n - i + 2,…, n )一共有n - i + 1种,然后每种的排列有i!个。

    所有长度为i的字段对答案的贡献 = 不同子段的出现个数 × 符合的长度为i子段的个数

    = n!× (n - i + 1) / ( n!/ ( n - i )!) × ( n - i + 1 ) × i!

    = ( n - i )! × ( n - i + 1) × ( n - i +1 ) × i!

    这个式子看上去挺好看的,然后求个总和就好。

    代码特别短:

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <algorithm>
     4 #include <cstring>
     5 #include <vector>
     6 #define rep(x, l, r) for(int x = l; x <= r; x++)
     7 #define repd(x, r, l) for(int x = r; x >= l; x--)
     8 #define clr(x, y) memset(x, y, sizeof(x))
     9 #define all(x) x.begin(), x.end()
    10 #define pb push_back
    11 #define mp make_pair
    12 #define MAXN 250005
    13 #define fi first
    14 #define se second
    15 #define SZ(x) ((int)x.size())
    16 using namespace std;
    17 typedef long long ll;
    18 typedef vector<int> vi;
    19 typedef pair<int, int> pii;
    20 const int INF = 1 << 30;
    21 int p;
    22 int lowbit(int x){ return x & (-x);}
    23 int fast_power(int a, int b){ int x; for(x = 1; b; b >>= 1){ if(b & 1) x = 1ll * x * a % p; a = 1ll * a * a % p;} return x % p;}
    24 
    25 int pow[MAXN];
    26 
    27 int main(){
    28     int n;
    29     scanf("%d%d", &n, &p);
    30     pow[0] = 1;
    31     rep(i, 1, n){
    32         pow[i] = 1ll * pow[i - 1] * i % p;
    33     }
    34     int ans = 0;
    35     rep(i, 1, n){
    36         int s = 1ll * pow[n - i] * (n - i + 1) % p * (n - i + 1) % p * pow[i] % p;
    37         ans = (ans + s) % p;
    38     }
    39     printf("%d
    ", ans);
    40     return 0;
    41 }
    View Code-C

    D.New Year and Conference

    题目大意:有n个人,每个人在a会场讲话开始时间为sai,结束时间为eai,在b会场开始时间为sbi,结束时间为ebi。是否存在一个集合中的人在a市场没有时间重叠在b市场有重叠或在b市场没有重叠在a市场有有重叠。设两个人开始结束时间分别为(u,v)和(x,y),当max(x,u) <= min(y,v)时两人重叠。存在重叠时输出“NO”,否则输出“YES”(似乎有什么不对的地方)

    提前申明一下,这道题我自己代码一直过不了,但是群里有人按照我的解法过了……代码也差不多……

    只WA了第10个点(加了个特判过了),现在对拍跑了2个半小时还没跑出一组错误数据……

    我的解法甚是奇怪……

    首先判断a会场不重叠b会场重叠的情况,发现我们对于每个人a会场只要判断左边不重叠的情况,右边的到时候会枚举到的。

    对于i这个人,要是eaj < sai,那么这两个人就不会重叠。

    所以我们以sai为关键字进行排序,二分查找可以找出所有与i不重叠的人。

    但是对每个人找他左边的人的区间肯定要超时,因为左边的人一定是从1开始的一个区间,我们记录下对于每个人i所有的以i为最右边的不重叠的人pi,j。(即不存在一个人k使得eai < eak < sapi,j

    然后只需要判断b会场是否有重叠,也就是说对第i个人,所有他左边的不重叠人j的[sbjebj]这个区间是否和[sbi,ebi]有重合,变成了一个区间覆盖问题。

    用线段树进行维护,将区间[sbi,ebi]更改为已覆盖,判断pi中是否有点的讲话区间中有已覆盖的点。

    对于另一种情况b会场不重叠a会场重叠情况和这个相同。

    放上我的WA掉的代码(仅供参考,对着打出锅了别怪我):

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <algorithm>
      4 #include <cstring>
      5 #include <vector>
      6 #define rep(x, l, r) for(int x = l; x <= r; x++)
      7 #define repd(x, r, l) for(int x = r; x >= l; x--)
      8 #define clr(x, y) memset(x, y, sizeof(x))
      9 #define all(x) x.begin(), x.end()
     10 #define pb push_back
     11 #define mp make_pair
     12 #define MAXN 500005
     13 #define MAXM 2000005
     14 #define fi first
     15 #define se second
     16 #define SZ(x) ((int)x.size())
     17 using namespace std;
     18 typedef long long ll;
     19 typedef vector<int> vi;
     20 typedef pair<int, int> pii;
     21 const int INF = 1 << 30;
     22 const int p = 1000000009;
     23 int lowbit(int x){ return x & (-x);}
     24 int fast_power(int a, int b){ int x; for(x = 1; b; b >>= 1){ if(b & 1) x = 1ll * x * a % p; a = 1ll * a * a % p;} return x % p;}
     25 
     26 struct node1{
     27     int l1, r1, l2, r2;
     28 }a[MAXN];
     29 struct node2{
     30     int l, r;
     31     bool flag, tag;
     32 }tree[MAXM];
     33 bool ans;
     34 int num[MAXM];
     35 vi ve1[MAXN], ve2[MAXN];
     36 
     37 void pushup(int q){
     38     tree[q].flag = tree[q << 1].flag || tree[q << 1 | 1].flag;
     39 }
     40 
     41 void pushdown(int q){
     42     if(!tree[q].tag) return;
     43     tree[q << 1].flag = tree[q << 1].tag = 1;
     44     tree[q << 1 | 1].flag = tree[q << 1 | 1].tag = 1;
     45     tree[q].tag = 0;
     46 }
     47 
     48 void build(int q, int l, int r){
     49     tree[q].l = l;
     50     tree[q].r = r;
     51     tree[q].tag = 0;
     52     tree[q].flag = 0;
     53     if(l == r) return;
     54     int mid = (l + r) >> 1;
     55     build(q << 1, l, mid);
     56     build(q << 1 | 1, mid + 1, r);
     57     pushup(q);
     58 }
     59 
     60 void update(int q, int l, int r){
     61     if(tree[q].l > r || tree[q].r < l) return;
     62     if(tree[q].l >= l && tree[q].r <= r){
     63         tree[q].flag = 1;
     64         tree[q].tag = 1;
     65         return;
     66     }
     67     pushdown(q);
     68     update(q << 1, l, r);
     69     update(q << 1 | 1, l, r);
     70     pushup(q);
     71 }
     72 
     73 void query(int q, int l, int r){
     74     if(tree[q].l > r || tree[q].r < l) return;
     75     if(tree[q].l >= l && tree[q].r <= r){
     76         ans = ans || tree[q].flag;
     77         return;
     78     }
     79     pushdown(q);
     80     query(q << 1, l, r);
     81     query(q << 1 | 1, l, r);
     82     pushup(q);
     83 }
     84 
     85 bool cmp1(node1 a, node1 b){
     86     return a.r1 < b.r1;
     87 }
     88 
     89 bool cmp2(node1 a, node1 b){
     90     return a.r2 < b.r2;
     91 }
     92 
     93 int main(){
     94     int n, m = 0;
     95     scanf("%d", &n);
     96     rep(i, 1, n){
     97         scanf("%d%d%d%d", &a[i].l1, &a[i].r1, &a[i].l2, &a[i].r2);
     98         num[++m] = a[i].l1;
     99         num[++m] = a[i].r1;
    100         num[++m] = a[i].l2;
    101         num[++m] = a[i].r2;
    102     }
    103     sort(num + 1, num + m + 1);
    104     rep(i, 1, n){
    105         a[i].l1 = lower_bound(num + 1, num + m + 1, a[i].l1) - num;
    106         a[i].r1 = lower_bound(num + 1, num + m + 1, a[i].r1) - num;
    107         a[i].l2 = lower_bound(num + 1, num + m + 1, a[i].l2) - num;
    108         a[i].r2 = lower_bound(num + 1, num + m + 1, a[i].r2) - num;
    109     }
    110     sort(a + 1, a + n + 1, cmp1);
    111     rep(i, 1, n){
    112         int l = 1, r = n, ans = 0;
    113         while(l <= r){
    114             int mid = (l + r) >> 1;
    115             if(a[mid].r1 < a[i].l1){
    116                 ans = mid;
    117                 l = mid + 1;
    118             }
    119             else r = mid - 1;
    120         }
    121         ve1[ans].pb(i);
    122     }
    123     build(1, 1, m);
    124     rep(i, 1, n){
    125         update(1, a[i].l2, a[i].r2);
    126         rep(j, 0, SZ(ve1[i]) - 1){
    127             int x = ve1[i][j];
    128             ans = 0;
    129             query(1, a[x].l2, a[x].r2);
    130             if(ans){
    131                 puts("NO");
    132                 return 0;
    133             }
    134         }
    135     }
    136     sort(a + 1, a + n + 1, cmp2);
    137     rep(i, 1, n){
    138         int l = 1, r = n, ans = 0;
    139         while(l <= r){
    140             int mid = (l + r) >> 1;
    141             if(a[mid].r2 < a[i].l2){
    142                 ans = mid;
    143                 l = mid + 1;
    144             }
    145             r = mid - 1;
    146         }
    147         ve2[ans].pb(i);
    148     }
    149     build(1, 1, m);
    150     rep(i, 1, n){
    151         update(1, a[i].l1, a[i].r1);
    152         rep(j, 0, SZ(ve2[i]) - 1){
    153             int x = ve2[i][j];
    154             ans = 0;
    155             query(1, a[x].l1, a[x].r1);
    156             if(ans){
    157                 puts("NO");
    158                 return 0;
    159             }
    160         }
    161     }
    162     puts("YES");
    163     return 0;
    164 }
    View Code-D
  • 相关阅读:
    数据可视化实例(八): 边缘直方图(matplotlib,pandas)
    数据可视化实例(七): 计数图(matplotlib,pandas)
    数据可视化实例(六): 带线性回归最佳拟合线的散点图(matplotlib,pandas)
    python 并发专题(十四):asyncio (三)实战
    python 并发专题(十三):asyncio (二) 协程中的多任务
    python 并发专题(十三):asyncio (一) 初识
    python 面向对象专题(七):异常处理
    JavaScript手册 | JS Array 对象中的unshift() 方法
    Spring框架:Bean Scopes, 声明一个Bean的范围
    Java 方法
  • 原文地址:https://www.cnblogs.com/nblyz2003/p/12151883.html
Copyright © 2020-2023  润新知