2020 CCPC Wannafly Winter Camp Day1 Div.1&2总结

期望逆序对
密码学 模拟
染色图
生成树
树与路径
乘法 二分
圆凸包
最大公约数 唯一分解定理
k小数查询 区间线段树套权值线段树
德州扑克

B密码学

注意题目是给出所有操作后的结果,所以需要逆着操作即可

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <vector>
#include <map>
#include <set>
#include <cmath>
#include <algorithm>
#define ll long long
using namespace std;
const int maxn = 1e3+5;
const int inf = 0x3f3f3f3f;
char s[1005][105];
char t[1005][105];
int n,m;
int xx[1005],yy[1005];
char change(char a,char b){//a是破解后的
    int aa = 0,bb = 0,cc = 0;
    if(a >= 'a' && a <= 'z')aa = a - 'a';
    else aa = a - 'A' + 26;
    if(b >= 'a' && b <= 'z')bb = b - 'a';
    else bb = b - 'A' + 26;

    if(aa >= bb){
        cc = aa - bb; 
    }else{
        cc = aa + 52 - bb;
    }
    aa = aa % 52;
    if(cc >= 0 && cc <= 25)return cc + 'a';
    else return cc - 26 + 'A';
}
void solve(){
    for(int i = m; i >= 1; i--){
        char x[105],y[105];
        strcpy(x,t[xx[i]]);
        strcpy(y,t[yy[i]]); 
        int l1 = strlen(x);
        int l2 = strlen(y);
        for(int j = 0; j < l2; j++){
            y[j] = change(y[j],x[j%l1]);
        }
        strcpy(t[yy[i]],y);
    }
}
void print(){
    for(int i = 1; i <= n; i++){
        cout << t[i] << endl;
    }
}
int main(){
    cin >> n >> m;
    for(int i = 1; i <= m; i++){
        scanf("%d%d",&xx[i],&yy[i]);
    }   
    for(int i = 1; i <= n; i++){
        cin >> s[i];
        strcpy(t[i],s[i]);
    }
    solve();
    print();
    return 0;
}

F乘法

二分第k小的数字,mid 是一个数字,然后在数组b中进行遍历,看看这个数字在所有数字的排名情况
求出mid在一个常数*a[j]的所有情况的排名很简单,对于常数是0的情况,常数>0的情况,常数<0的情况,二分即可。
很妙的想法

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#define ll long long
using namespace std;
const int maxn = 1e5 + 5;
ll a[maxn],b[maxn];
ll n,m,k;
bool check(ll mid){
    ll cnt = 0;
    for(int i = 1; i <= m; i++){
        if(b[i] == 0)cnt += mid<0?n:0;
        if(b[i] < 0)cnt += lower_bound(a + 1, a + n + 1, ceil((double)mid / b[i])) - (a + 1);
        if(b[i] > 0)cnt += n - ((upper_bound(a + 1, a + n + 1, floor((double)mid / b[i]))) - (a + 1));
        // cout << cnt << endl;
    }
    return cnt <= k;
}
int main(){
    cin >> n >> m >> k;
    k--;
    for(int i = 1; i <= n; i++){
        scanf("%lld",&a[i]);
    }
    for(int i = 1; i <= m; i++){
        scanf("%lld",&b[i]);
    }
    sort(a + 1,a + n + 1);
    sort(b + 1,b + m + 1);
    ll l = -1e13,r = 1e13;
    while(l + 1 < r){
        ll mid = (l + r) >> 1;
        // cout << l << " " << mid << " " << r << endl;
        if(check(mid))r = mid;
        else l = mid;
    }
    cout << r << endl;
    return 0;
}

H最小公约数

只需要对于gcd(i,y)对于i是[1,n]中除了k以外都不满足gcd(i,y) = gcd(k,y)
也就是gcd(y,k)的值是唯一的
而y只能是y的倍数才行,否则,对于k是质数的情况,gcd(k,y)会是1
那么只需要令ans = k,遍历[1,n]中k的倍数即可,如果说i是质数,那么乘上ans,因为根据唯一分解定理,所有数可以由质数乘积表示,要求出最小y,那么只需要质数即可,而ans初始值为k,因为y必须是k的倍数

import math
def is_prime(n):
    if n == 1:
        return False
    for i in range(2, int(math.sqrt(n)) + 1):
        if n % i == 0:
            return False;
    return True
t = int(input())
for tt in range(1, t + 1):
    n, k = map(int, input().split())
    ans = k
    i = 2
    while i * k <= n:
        if is_prime(i):
            ans *= i
        i = i + 1
    print(ans)

K小数查询

n,m的范围是\(8*10^{4}\)
一种方法是可以暴力O(nm)
一种方法是主席树

#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;
const int maxn = 1e5 + 5;
int n,m;
int a[maxn];
int t[maxn];
int main(){
    scanf("%d%d",&n,&m);
    for(int i = 1; i <= n; i++)scanf("%d",&a[i]);
    while(m--){
        int c,l,r,k;
        scanf("%d%d%d%d",&c,&l,&r,&k);
        if(c == 1){
            for(int i = l; i <= r; i++){
                a[i] = min(a[i],k);
            }
        }else{
            int sum = 0,last = 0;
            memset(t,0,sizeof(t));
            for(int i = l; i <= r; i++){
                t[a[i]]++;
            }
            for(int i = 1; i <= n; i++){
                last = sum;
                sum += t[i];
                if(last < sum && sum >= k){
                    printf("%d\n",i);
                    break;
                }
            }
        }
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/Emcikem/p/12220832.html