码迷,mamicode.com
首页 > 其他好文 > 详细

Codeforces Round #602 (Div. 2, based on Technocup 2020 Elimination Round 3)

时间:2019-11-24 21:13:38      阅读:84      评论:0      收藏:0      [点我收藏+]

标签:mat   时间复杂度   依次   include   data-   cli   return   方法   排序   

A.Math Problem(CF 1262 A)

题目大意:给定n条线段,求一条线段,使得这个线段能够跟所有给定的线段都相交(端点值一样也算相交),最小化它的长度,可以是0.

很显然找出这n条线段的左端点最大值和右端点的最小值,它们的差和0的最大值即为答案。

 

技术图片
 1 #include <bits/stdc++.h>
 2 #define MIN(a,b) (((a)<(b)?(a):(b)))
 3 #define MAX(a,b) (((a)>(b)?(a):(b)))
 4 using namespace std;
 5 
 6 template <typename T>
 7 void read(T &x) {
 8     int s = 0, c = getchar();
 9     x = 0;
10     while (isspace(c)) c = getchar();
11     if (c == 45) s = 1, c = getchar();
12     while (isdigit(c)) x = (x << 3) + (x << 1) + (c ^ 48), c = getchar();
13     if (s) x = -x;
14 }
15 
16 template <typename T>
17 void write(T x, char c =  ) {
18     int b[40], l = 0;
19     if (x < 0) putchar(45), x = -x;
20     while (x > 0) b[l++] = x % 10, x /= 10;
21     if (!l) putchar(48);
22     while (l) putchar(b[--l] | 48);
23     putchar(c);
24 }
25 
26 void Input(void) {
27     int n,l,r;
28     l=0;
29     r=1e9+7;
30     read(n);
31     for(int u,v,i=1;i<=n;++i){
32         read(u);
33         read(v);
34         l=MAX(l,u);
35         r=MIN(v,r);
36     }
37     printf("%d\n",MAX(l-r,0));
38 }
39 
40 void Solve(void) {}
41 
42 void Output(void) {}
43 
44 main(void) {
45     int kase;
46     freopen("input.txt", "r", stdin);
47     freopen("output.txt", "w", stdout);
48     read(kase);
49     for (int i = 1; i <= kase; i++) {
50         //printf("Case #%d: ", i);
51         Input();
52         Solve();
53         Output();
54     }
55 }
神奇的代码

 

B.Box(CF 1262 B)

题目大意:给出一个排列每一个位置的前缀最大值,还原该排列,答案可能有多种,还原任意一种即可。

输入max[i],如果max[i-1]<max[i],则第i位一定是max[i].

如果max[i-1]=max[i],则我们可以选择小于max[i]的未出现的数作为第i位,贪心构造即可。当没有数可以选择的时候则说明没有排列满足该条件。

 

技术图片
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 template <typename T>
 5 void read(T &x) {
 6     int s = 0, c = getchar();
 7     x = 0;
 8     while (isspace(c)) c = getchar();
 9     if (c == 45) s = 1, c = getchar();
10     while (isdigit(c)) x = (x << 3) + (x << 1) + (c ^ 48), c = getchar();
11     if (s) x = -x;
12 }
13 
14 template <typename T>
15 void write(T x, char c =  ) {
16     int b[40], l = 0;
17     if (x < 0) putchar(45), x = -x;
18     while (x > 0) b[l++] = x % 10, x /= 10;
19     if (!l) putchar(48);
20     while (l) putchar(b[--l] | 48);
21     putchar(c);
22 }
23 int n,l,ans[100050];
24 bool used[100050];
25 void Input(void) {
26     read(n);
27     for(int i=1;i<=n;++i) used[i]=true;
28     l=1;
29     ans[0]=0;
30     bool qwq=false;
31     for(int u,v=0,i=1;i<=n;++i){
32         read(u);
33         if (qwq) continue;
34         if (u>v){
35             used[u]=false;
36             ans[i]=u;
37             v=u;
38             continue;
39         }
40         while(l<u&&used[l]==false) ++l;
41         if (l==u){
42             qwq=true;
43             continue;
44         }
45         ans[i]=l;
46         used[l]=false;
47     }
48     if (qwq) printf("-1\n");
49     else{
50         for(int i=1;i<=n;++i) printf("%d%c",ans[i],i==n?\n: );
51     }
52 }
53 
54 void Solve(void) {}
55 
56 void Output(void) {}
57 
58 main(void) {
59     int kase;
60     freopen("input.txt", "r", stdin);
61     freopen("output.txt", "w", stdout);
62     read(kase);
63     for (int i = 1; i <= kase; i++) {
64         //printf("Case #%d: ", i);
65         Input();
66         Solve();
67         Output();
68     }
69 }
神奇的代码

 

C.Messy

题目大意:给定一个括号串,我们可以翻转某一区间的括号,即对[l...r]翻转,则变成[r...l],然后我们需要进行不超过n次操作,使得该括号串合法,且对于所有该串的前缀子串,有k个合法子串,输出操作次数以及前后分别进行的操作的区间的左端点和右端点,注意只要小于n即可,不需要最小。题目保证有解。

所有子串有k个合法前缀子串,即整个子串分成了k份,我们对某一份中的()交换,则将该份子串拆成两份,我们把两份子串的接触点)(交换,则这两个子串合并成一个,所以我们关键是如何让该子串合法,然后就不会了qwq

坑待填

 

 

D.Optimal Subsequences(CF 1262 D1、D2)

题目大意:给定一个长度为n的数组,求一个长度为k的最佳序列,该序列满足两个条件:其和是所有长度相同的序列的和的最大值;该序列是所有长度相同且和最大的序列中,其数字构成的序列的字典序最小,输出该序列的第pos位的数字,多次询问。

很容易想到我们可以先对k进行从小到大排序,依次构造出长度为k的最佳序列,其构造方法很容易想到,即设最佳序列的数组为a,数大的先添加进a数组,数相等的位置在前的先添加。

但关键在于如何找到该序列中第pos位的数字。

我们新设一个数组cnt,cnt[i]表示第i个数字被选中了,记为1,否则为0,然后我们用树状数组来维护cnt数组的前缀和,当某位的前缀和为pos,且该位被选中了,则该位的数字即为所求答案。由于前缀和单调递增,我们可以采用二分,即可在O(log2n)时间内找出。

总时间复杂度是O(mlog2n+mlogm)

 

当时做的时候逆过来,k从大到小排序,然后在原数组删数,树状数组维护前i个数中被删去的个数,则对于在原数组第i位且未被删去的数,它在最佳序列的位置即为i-sum[i],同样二分找即可。

技术图片
  1 #include <bits/stdc++.h>
  2 #define lowbit(x)  ((x&(-x)))
  3 using namespace std;
  4 
  5 template <typename T>
  6 void read(T &x) {
  7     int s = 0, c = getchar();
  8     x = 0;
  9     while (isspace(c)) c = getchar();
 10     if (c == 45) s = 1, c = getchar();
 11     while (isdigit(c)) x = (x << 3) + (x << 1) + (c ^ 48), c = getchar();
 12     if (s) x = -x;
 13 }
 14 
 15 template <typename T>
 16 void write(T x, char c =  ) {
 17     int b[40], l = 0;
 18     if (x < 0) putchar(45), x = -x;
 19     while (x > 0) b[l++] = x % 10, x /= 10;
 20     if (!l) putchar(48);
 21     while (l) putchar(b[--l] | 48);
 22     putchar(c);
 23 }
 24 
 25 struct data{
 26     int val,id;
 27     bool operator < (const data &b) const{
 28         if (val>b.val) return true;
 29         if (val<b.val) return false;
 30         if (id<b.id) return true;
 31         return false;
 32     }
 33 };
 34 
 35 const int N=2e5+5;
 36 
 37 struct date{
 38     int k,pos,id;
 39 }que[N];
 40 
 41 priority_queue<data> qwq;
 42 
 43 int n,m;
 44 
 45 int tree[N],a[N],ans[N];
 46 
 47 bool dell[N];
 48 
 49 bool cmp(const struct date &a,const struct date &b){
 50     if (a.k>b.k) return true;
 51     if (a.k<b.k) return false;
 52     if (a.pos<b.pos) return false;
 53     return true;
 54 }
 55 
 56 void Input(void) {
 57     read(n);
 58     for(int i=1;i<=n;++i) {
 59         read(a[i]);
 60         qwq.push(data{a[i],i});
 61     }
 62     read(m);
 63     for(int i=1;i<=m;++i){
 64         que[i].id=i;
 65         read(que[i].k);
 66         read(que[i].pos);
 67     }
 68 }
 69 
 70 void tree_insert(int x){
 71     for(int i=x;i<=n;i+=lowbit(i))
 72         tree[i]++;
 73 }
 74 
 75 int tree_sum(int x){
 76     int a=0;
 77     for(int i=x;i>=1;i-=lowbit(i))
 78         a+=tree[i];
 79     return a;
 80 }
 81 
 82 int find_pos(int x){
 83     int l=1,r=n;
 84     while(l<=r){
 85         int mid=(l+r)>>1;
 86         int tmp=tree_sum(mid);
 87         if (mid-tmp>x) r=mid;
 88         else if (mid-tmp==x) if (dell[mid]==false) return a[mid];
 89         else r=mid;
 90         else l=mid+1;
 91     }
 92     return 0;
 93 } 
 94 
 95 void Solve(void) {
 96     sort(que+1,que+1+m,cmp);
 97     int qvq=n;
 98     for(int i=1;i<=m;++i){
 99         int dis=qvq-que[i].k;
100         qvq=que[i].k;
101         while(dis--){
102             data qaq=qwq.top();
103             dell[qaq.id]=true;
104             tree_insert(qaq.id);
105             qwq.pop();
106         }
107         ans[que[i].id]=find_pos(que[i].pos);
108     }
109 }
110 
111 void Output(void) {
112     for(int i=1;i<=m;++i) printf("%d\n",ans[i]);
113 }
114 
115 main(void) {
116     freopen("input.txt", "r", stdin);
117     freopen("output.txt", "w", stdout);
118     Input();
119     Solve();
120     Output();
121 }
神奇的代码

(以为会T的结果才跑了200+ms?)

 

Codeforces Round #602 (Div. 2, based on Technocup 2020 Elimination Round 3)

标签:mat   时间复杂度   依次   include   data-   cli   return   方法   排序   

原文地址:https://www.cnblogs.com/Lanly/p/11924231.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!