链接: Educational Codeforces Round 102 (Rated for Div. 2).
A
题意:输入n,d,有n个数,可以选择互不想等的i,j,k,使得ai=aj+ak。问最终能否使得数组的每个数字都小于等于d
思路:求出数组最小的两个数的和,小于d就YES,否则NO
代码
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <vector>
#include <list>
#include <set>
#include <utility>
#include <map>
#include <iostream>
#include <sstream>
#include <algorithm>
#include <string>
#include <stack>
#include <queue>
#include <fstream>
#include <bitset>
using namespace std;
#define pi acos(-1)
#define INF 0x3f3f3f
#define T int T;scanf("%d",&T);while(T--)
#define ll long long
#define ull unsigned long long
const int maxn = 1e5+10;
int a[maxn];
int main(){
T{
int n,d;
cin >> n >> d;
int p = 1;
for(int i = 0; i < n; i++){
int x;
cin >> a[i];
if(a[i]>d) p = 0;
}
if(p){
cout << "YES" << endl;
continue;
}
if(n==1){
if(a[0]>d) cout << "NO" << endl;
else cout << "YES" << endl;
continue;
}
sort(a,a+n);
if(a[0]+a[1]<=d) cout << "YES" << endl;
else cout << "NO" << endl;
}
return 0;
}
B
题意:有两个字符串s1和s2,问两个字符串变成同样长度时是不是相等,相等输出-1,相等就输出相等的字符串。
思路:模拟,求出两个字符串的lcm,判断是否相等
代码
#include <bits/stdc++.h>
using namespace std;
#define pi acos(-1)
#define INF 0x3f3f3f
#define T int T;scanf("%d",&T);while(T--)
#define ll long long
#define ull unsigned long long
const int maxn = 1e5+10;
int main(){
T{
string s1,s2;
cin >> s1 >> s2;
int len1 = s1.size();
int len2 = s2.size();
int lll = len1*len2/__gcd(len1,len2);
string ss = "";
for(int i = 0; i < lll/len1; i++){
ss += s1;
}
string sss = "";
for(int i = 0; i < lll/len2; i++){
sss += s2;
}
if(ss==sss){
cout << ss << endl;
}else cout << -1 << endl;
}
return 0;
}
C
题意:输入n和k,数组a是从1到k,k到2k-n的数组。b[i] = p[a[i]],要求数组b的逆序对数量小于等于a,求p数组字典序最大,p是1到k的一个排列。
思路:打表发现,p数组是a序列第k个数开始到最后一个数,然后在这段数前面从1开始添加数,直到p数组的数字个数等于k为止。
比如a[] = {1,2,3,4,5,6,5,4,3} ——> p[] = {1,2,6,5,4,3};
打表代码
#include <bits/stdc++.h>
using namespace std;
int a[110];
int p[110];
int b[110];
int main()
{
int n, k;
while(cin>>n>>k) {
for(int i = 1; i <= k; i++) {
a[i] = i;
}
int num = k;
for(int i = k+1; i <= n; i++) {
a[i] = --num;
}
for(int i = 1; i <= n; i++) {
cout << a[i] << " ";
}
cout << endl;
// for(int i = 1; i <= n; i++) {
// cout << a[i] << " ";
// }
// cout << endl;
int c1 = 0;
for(int i = 1; i <= n; i++) {
for(int j = i+1; j <= n; j++) {
if(a[i]>a[j]) {
c1++;
}
}
}
cout << c1 << endl;
for(int i = 0; i < k; i++) {
p[i] = i+1;
}
do{
for(int i = 1; i <= n; i++) {
b[i] = p[a[i]-1];
}
int c2 = 0;
for(int i = 1; i <= n; i++) {
for(int j = i+1; j <= n; j++) {
if(b[i]>b[j]) {
c2++;
}
}
}
if(c2<=c1) {
for(int i = 0; i < k; i++) {
cout << p[i] << " ";
}
cout << endl;
for(int i = 1; i <= n; i++) {
cout << b[i] << " ";
}
cout << endl;
}
}while(next_permutation(p,p+k));
}
return 0;
}
代码
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <vector>
#include <list>
#include <set>
#include <utility>
#include <map>
#include <iostream>
#include <sstream>
#include <algorithm>
#include <string>
#include <stack>
#include <queue>
#include <fstream>
#include <bitset>
using namespace std;
#define pi acos(-1)
#define INF 0x3f3f3f
#define T int T;scanf("%d",&T);while(T--)
#define ll long long
#define ull unsigned long long
const int maxn = 1e5+10;
int main(){
T{
int n,k;
scanf("%d %d", &n, &k);
int p = 2*k-n;
int f = 1;
for(int i = 1; i < p; i ++){
if(f) f = 0;
else printf(" ");
cout << i;
}
for(int i = k; i >= p; i --){
if(f) f = 0;
else printf(" ");
cout << i;
}
cout << endl;
}
return 0;
}
D
题意:有一个长度为n,只包含+ 和 -的字符串,+表示+1,-表示-1,x初始为0,有q次询问,每次询问输入一个区间表示该区间的符号忽略,问执行剩下的符号过程中出现几个不同的数。
思路:首先,如果不忽略任何符号,出现不同数的个数就是过程中出现的最大值-最小值+1。如果删去区间,就分三种情况(每一种情况的最大值最小值都要与0做比较,看看知否包含了0)
1、忽略区间为 [x,n],那么个数就考虑[1,x-1]这个区间最大值最小值与0的关系,求出个数。
2、忽略区间为 [1,y],那么个数就等于[y+1,n]这个区间的最大值最小值都减去前面忽略的这段区间的贡献的值,然后再与0比较,求出个数
3、忽略的区间在中间,那么求出剩下的左边区间的极值,和剩下右边区间的极值(注意这里要消除忽略区间的贡献),然后取出总的极值,然后判断与0的关系,求出个数。
首先用求出到每个位置的值,查询极值用线段树维护。
代码
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <vector>
#include <list>
#include <set>
#include <utility>
#include <map>
#include <iostream>
#include <sstream>
#include <algorithm>
#include <string>
#include <stack>
#include <queue>
#include <fstream>
#include <bitset>
using namespace std;
#define pi acos(-1)
#define inf 0x3f3f3f
#define T int T;scanf("%d",&T);while(T--)
#define ll long long
#define ull unsigned long long
const int maxn = 2e5+10;
int a[maxn];
struct node{
int l,r;
ll add;
ll sum;
ll maxx;
ll minn;
}tree[maxn<<2];
void pushup(int index){ //更新值
tree[index].sum = tree[index<<1].sum+tree[index<<1|1].sum;
tree[index].maxx = max(tree[index<<1].maxx,tree[index<<1|1].maxx);
tree[index].minn = min(tree[index<<1].minn,tree[index<<1|1].minn);
}
void build(int l, int r, int index){ //建树 数组a的l,r区间建树
tree[index].l = l;
tree[index].r = r;
tree[index].add = 0;
if(l == r){
tree[index].sum = tree[index].maxx = tree[index].minn = a[l];
return;
}
int mid = (l+r)>>1;
build(l,mid,index<<1);
build(mid+1,r,index<<1|1);
pushup(index);
}
ll query(int l,int r,int index){ //查询max
if(l <= tree[index].l && r >= tree[index].r){
return tree[index].maxx;
}
int mid = (tree[index].l + tree[index].r)>>1;
ll maxx = -inf;
if(l <= mid){
maxx = max(maxx,query(l,r,index<<1));
}
if(r > mid){
maxx = max(maxx,query(l,r,index<<1|1));
}
return maxx; //区间最大值
}
ll query2(int l,int r,int index){ //查询min
if(l <= tree[index].l && r >= tree[index].r){
return tree[index].minn;
}
int mid = (tree[index].l + tree[index].r)>>1;
ll minn = inf;
if(l <= mid){
minn = min(minn,query2(l,r,index<<1));
}
if(r > mid){
minn = min(minn,query2(l,r,index<<1|1));
}
return minn; //区间最小值
}
int main(){
int n,m;
T{
scanf("%d %d", &n, &m);
string s;
cin >> s;
for(int i = 0; i < s.size(); i++){
if(s[i]=='+') a[i+1] = a[i]+1;
else a[i+1] = a[i]-1;
}
build(1,n,1); //每个位置的值建树
while(m--){
int x,y;
cin >> x >> y;
if(x==1&&y==n){ //如果忽略了整个区间,就输出1
cout << 1 << endl;
}else if(x==1){
int big = query(y+1,n,1)-a[y]; //极值要消除忽略了的区间的贡献
int small = query2(y+1,n,1)-a[y];
if(big<0&&small<0){ //如果极值的区间不包含0,且小于0
cout << 0-small+1 << endl;
}else if(big>0&&small>0){ //如果极值区间不包含0,且大于0
cout << big-0+1 << endl;
}else{ //包含0
cout << big-small+1 << endl;
}
}else if(y==n){
int big = query(1,x-1,1);
int small = query2(1,x-1,1);
if(big<0&&small<0){
cout << 0-small+1 << endl;
}else if(big>0&&small>0){
cout << big-0+1 << endl;
}else{
cout << big-small+1 << endl;
}
}else{
int b1 = query(1,x-1,1); //左边区间的极值
int s1 = query2(1,x-1,1);
int b2 = query(y+1,n,1); //右边区间的极值
int s2 = query2(y+1,n,1);
int tt = a[y]-a[x-1]; //忽略区间的贡献
b2-=tt; //右边区间要消除忽略区间的贡献
s2-=tt;
int big = max(b1,b2);
int small = min(s1,s2);
if(big<0&&small<0){
cout << 0-small+1 << endl;
}else if(big>0&&small>0){
cout << big-0+1 << endl;
}else{
cout << big-small+1 << endl;
}
}
}
}
return 0;
}