杭电九补题

杭电九补题

Dota2 Pro Circuit(whm出

题意:(1<=T<=20)

给两个数组a,b,(0<=ai<=1e9)都有n(1<=n<=5e3)个数,ai可以和任意的bj加起来得到到后面的ai,但是每个bj只能被加一次,问按照处理过的ai从大到小排名

最好的排名和最小的排名分别是多少

题解

双指针,对于一个数和一定加最大bj加起来位tmp,最好情况是,比他大的数ak匹配某个数x,ak + x 是小于tmp的最大数

由于初始化的原因,所以要注意

3

1 1 1

5 5 5

的情况

因为并列算排名都算最好的排名

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAX = 5e3 + 10;
struct node{
    int id;
    int val;
}c[MAX];
int a[MAX];
int b[MAX];
pair<int, int> ans[MAX];
int n;
ll good(int id) {
    int i = n - 1, j = n - 2;
    int cnt = n - 1;
    ll tmp = a[id] + b[n - 1];
    while(1){
        if(i < 0 || j < 0) break;
        if(i == id) {
            i--;
            continue;
        }
        while(a[i] + b[j] > tmp) {
            j--;
        }
        if(i >= 0 && j >= 0) {
            cnt--;
        }
        i--;j--;
    }
    return cnt + 1;
}

ll bad(int id) {
    int i = 0, j = 1;
    int cnt = 0;
    ll tmp = a[id] + b[0];
    while(1){
        if(i >= n || j >= n) break;
        if(i == id) {
            i++;
            continue;
        }
        while(a[i] + b[j] <= tmp) {
            j++;
        }
        if(i < n && j < n) {
            cnt++;
        }
        i++;j++;
    }
    return cnt + 1;
}
int main() {
    int T;
    scanf("%d", &T);
    while(T--) {
        scanf("%d", &n);
        for(int i = 0; i < n; i++) {
            scanf("%d", &a[i]);
            c[i].val = a[i];
            c[i].id = i;
        }
        for(int i = 0; i < n; i++) {
            scanf("%d", &b[i]);
        }
        sort(c, c + n, [](node a, node b) {
                return a.val > b.val;
            });
        sort(a, a + n, [](int a, int b) {
            return a > b;
            });
        sort(b, b + n);
        for(int i = 0; i < n; i++) {
            ll goodd = good(i);
            ll badd = bad(i);
            int pos = c[i].id;
            ans[pos] = {goodd, badd};
        }
        for(int i = 0; i < n; i++) {
            printf("%d %d\n", ans[i].first, ans[i].second);
        }
    }
}

Integers Have Friends 2.0(赛后补

题意

求n个数(2<= n <= 2e5)每个数 a i ( 1 < = a i < = 4 e 12 ) a_i(1 <=a_i <= 4e12) ai(1<=ai<=4e12),问最多有多少数模上一个大于等于2的数m之后相等

题解

思路:已知所有数字模上m相等的数 ==》 减去m都是某个数的倍数 ==》 减去这些数字的任意一个剩下的数的绝对值都是某个数的倍数

那么n个数都减去某个数a[cha],其中满足某个数k的倍数的数的最大集合数是答案

可以再找一个数a[pos](为什么不找本身,因为减去自己变成0了呀

假设这也是答案在的集合中的数,那么他和其他数都是k的倍数,k可以表示为质因子的乘积

对于某个质因子,其他模这个数为0,则是属于某个集合中

假设k=6=3*k1(k1 = 2)带入上面更好理解

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

const int MAX = 2e6 + 100;
ll pri[MAX];
ll is_pri[MAX];
int cnt;
void init() {
    is_pri[0] = is_pri[1] = 1;
    for(int i = 2; i <= MAX; i++) {
        if(is_pri[i] == 0) {
            pri[cnt++] = i;
        }
        for(int j = 0; j < cnt && pri[j] * i <= MAX; j++) {
            is_pri[i * pri[j]] = 1;
            if(i % pri[j] == 0) break;
        }
    }
}
ll a[MAX / 10];
ll b[MAX / 10];

ll solve(ll cha, ll pos, int n) {
    for(int i = 0; i < n; i++) {
        b[i] = abs(a[i] - a[cha]);
    }
    ll tmp = b[pos];
    vector<ll> ans;
    for(int i = 0; pri[i] * pri[i] <= tmp && i < cnt; i++) {
        if(tmp % pri[i] == 0) {
            ans.push_back(pri[i]);
            while(tmp % pri[i] == 0) {
                tmp /= pri[i];
            }
        }
    }
    if(tmp != 1 && tmp != 0) {
        ans.push_back(tmp);
    }
    ll maxx = 1;
    for(auto x : ans) {        ll cnt = 0;
        for(ll i = 0; i < n; i++) {
            if(b[i] % x == 0) cnt++;
        }
        maxx = max(maxx, cnt);
    }
    return maxx;
}
int main() {
    init();
    int T;
    scanf("%d", &T);
    while(T--) {
        int n;
        scanf("%d", &n);
        for(int i = 0; i < n; i++) {
            scanf("%lld", &a[i]);
        }
        ll ans = 0;
        for(int i = 0; i < 33; i++) {
            ll aa = (rand()) % n;
            ll bb = (rand()) % n;
            ans = max(ans, solve(aa, bb, n));
        }
        printf("%lld\n", ans);
    }
}

Boring data structure problem

T个数(1<=T<=1e7)个操作L是从左边压入,R是从右边压入,G x是删掉x的值,Q是询问第(m + 1)/2的上取整个数

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAX = 2e7 + 10000;
int sizee;
#define lowbit(x) x & (-x)
int tr[MAX];
void insert(int k, int x) {
    while(k <= sizee) {
        tr[k] += x;
        k += lowbit(k);
    }
}

int query(int k) {
    int ans = 0;
    while(k > 0) {
        ans += tr[k];
        k -= lowbit(k);
    }
    return ans;
}

const int M = 1e7 + 100;
int idx[MAX] = {0};
int main() {
//    int  beg = clock();
    int T;
    scanf("%d", &T);
    sizee = MAX;
    int cnt = 0;
    int id = 0;
    while(T--) {
        char op[2];
        scanf("%s", op);
        if(op[0] == 'L') {
            insert(M - cnt, 1);
            idx[cnt] = M - cnt;
            cnt++;
            id++;

        }
        else if(op[0] == 'R') {
            insert(M + cnt, 1);
            idx[cnt] = M + cnt;
            cnt++;
            id++;
        }
        else if(op[0] == 'G') {
            int x;
            scanf("%d", &x);
            insert(idx[x - 1], -1);
            id--;
        }
        else {
            int tmp = (id + 2) / 2;
            int L = 1, R = MAX;
            while(L < R) {
                int mid = (L + R) / 2;
                if(query(mid) >= tmp) R = mid;
                else L = mid + 1;
            }
            if(L >= M) L = L - M;
            else L = M - L;
            printf("%d\n", L + 1);
        }
    }
//    int  endd = clock();
//    cerr<<(double)(endd - beg) /CLOCKS_PER_SEC << endl;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值