Educational Codeforces Round 102 (Rated for Div. 2) A-D

链接: 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;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值