题目大意:给定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?)