题目大意:给定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 }
题目大意:给出一个排列每一个位置的前缀最大值,还原该排列,答案可能有多种,还原任意一种即可。
输入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 }
题目大意:给定一个括号串,我们可以翻转某一区间的括号,即对[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?)
