洛谷7月月赛

【LGR-049】洛谷7月月赛

比赛开始一个小时才想起来QwQ,当场写了ABC

#A: P4752 Divided Prime

日常送分题 注意只留一个非1数判他是不是质数

#B: P4753 River Jumping

题意:有跳跃距离下限,求能否经过所有石头恰好一次跳一个来回

贪心

首先距离河岸最近的两个石头必须要能跳上,剩下最多的隔一个跳一个(因为是来回)

#C: P4754 True Vegetable

经典的二分+贪心

二分最小回合数,把所有菜气都减去,然后从左到右贪心加,bit维护

一开始以为r值没用,原来r值保证了答案的单调性

#D: P4755 Beautiful Pair

题意:小D有个数列 \({a}\) ,当一个数对 \((i,j)(i≤j)\) 满足 \(a_i*a_j \le \max(a_i,a_{i+1},…,a_j)\) ,小D认为这个数对是美丽的.请你求出美丽的数对的数量。

单调栈处理出每个值作为最大值的长度a_x [l,r]

然后对于[l,x]中每个值\(a_i\),找[x,r]中满足\(a_j \le \frac{a_x}{a_i}\)的数量,这里可以用主席树实现

但这样复杂度不对,可以选长度短的一段来枚举

复杂度 \(T(n) = T(a) + T(n-a-1) + O(n\log n) = O(n\log^2 n),其中a \le n/2\)

问了一下,可以数归证明。其实就是启发式合并

//D
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int N = 1e5+5;

int n, a[N], mp[N], m;
int st[N], top, l[N], r[N];
void init() {
    for(int i=1; i<=n; i++) {
        int le = i;
        while(top && a[st[top]] <= a[i]) {
            le = l[st[top]];
            r[st[top]] = i-1;
            top--;
        }
        st[++top] = i;
        l[i] = le;
    }
    while(top) r[st[top--]] = n;

    sort(mp+1, mp+1+n);
    m = unique(mp+1, mp+1+n) - mp - 1;
}


struct node {
    int lc, rc, size;
} t[N*18];
int sz, root[N];
void ins(int &x, int l, int r, int p) {
    t[++sz] = t[x]; x = sz;
    t[x].size ++;
    if(l == r) return;
    int mid = (l+r) >> 1;
    if(p <= mid) ins(t[x].lc, l, mid, p);
    else ins(t[x].rc, mid+1, r, p);
}
int que(int x, int y, int l, int r, int ql, int qr) {
    if(mp[r] < ql || qr < mp[l]) return 0;
    if(ql <= mp[l] && mp[r] <= qr) return t[y].size - t[x].size;
    int mid = (l+r) >> 1, ans = 0;
    if(ql <= mp[mid]) ans += que(t[x].lc, t[y].lc, l, mid, ql, qr);
    if(mp[mid] < qr) ans += que(t[x].rc, t[y].rc, mid+1, r, ql, qr);
    return ans;
}

long long ans;
void solve(int l1, int r1, int l2, int r2, int mid) { 
    for(int i=l1; i<=r1; i++) {
        int v = a[mid] / a[i];
        ans += que(root[l2-1], root[r2], 1, m, 1, v);
    }
}
int main() {
    freopen("in", "r", stdin);
    ios::sync_with_stdio(false); cin.tie(); cout.tie();
    cin >> n;
    for(int i=1; i<=n; i++) cin >> a[i], mp[i] = a[i];
    init();
    //for(int i=1; i<=n; i++) printf("hi %d [%d %d]\n", i, l[i], r[i]);
    for(int i=1; i<=n; i++) {
        int x = lower_bound(mp+1, mp+1+m, a[i]) - mp;
        root[i] = root[i-1];
        ins(root[i], 1, m, x);
    }
    for(int i=1; i<=n; i++) {
        int le = l[i], ri = r[i];
        int d1 = i-le, d2 = ri-i;
        //if(d1 == 0 || d2 == 0) continue;

        if(d1 <= d2) solve(le, i, i, ri, i);
        else solve(i, ri, le, i, i);
    }
    cout << ans;
}
//A
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
typedef long long ll;
using namespace std;
const int N = 1e5+5;

int n, m, c[N];
ll a[N], b[N], mp[N];

bool is_p(ll n) {
    for(ll i=2; i*i<=n; i++) if(n%i == 0) return false;
    return true;
}
int main() {
    freopen("in", "r", stdin);
    ios::sync_with_stdio(false);
    int T;
    cin >> T;
    while(T--) {
        mp[0] = 0;
        memset(c, 0, sizeof(c));
        cin >> n >> m;
        for(int i=1; i<=n; i++) cin >> a[i], mp[i] = a[i];
        sort(mp+1, mp+1+n);
        mp[0] = unique(mp+1, mp+1+n) -mp -1;

        for(int i=1; i<=n; i++) {
            int x = lower_bound(mp+1, mp+1+mp[0], a[i]) - mp;
            c[x]++;
        }
        for(int i=1; i<=m; i++) {
            cin >> b[i];
            int x = lower_bound(mp+1, mp+1+mp[0], b[i]) - mp;
            c[x]--;
        }

        int cnt = 0;
        ll ans = 0;
        for(int i=1; i<=mp[0]; i++) if(mp[i] != 1 && c[i]) {
            cnt+=c[i];
            ans = mp[i];
        }
        if(cnt!=1) puts("NO");
        else if(!is_p(ans)) puts("NO");
        else puts("YES");
    }
}
//B
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <vector>
typedef long long ll;
using namespace std;
const int N = 1e5+5;


int n, m, s, x[N], vis[N];
vector<int> v;
bool solve() {
    int now = 0;
    if(x[1] < s) return false;
    now = 1; vis[1] = 1; v.push_back(1);
    while(now+2 <= m) {
        if(x[now+2] - x[now] < s) return false;
        vis[now+2] = 1; v.push_back(now+2);
        now += 2;
    }
    if(now == m-1) {
        if(x[m] - x[now] < s) return false;
        vis[m] = 1; v.push_back(m);
        now ++;
    }
    for(int i=m-1; i>=0; i--) if(!vis[i]) {
        if(x[now] - x[i] < s) return false; 
        now = i; v.push_back(i);
    }
    return true;
}
int main() {
    freopen("in", "r", stdin);
    ios::sync_with_stdio(false);

    cin >> n >> m >> s;
    for(int i=1; i<=m; i++) cin >> x[i];
    x[0] = 0; x[++m] = n;
    
    if(!solve()) cout << "NO" << endl;
    else {
        cout << "YES" << endl;
        for(int i=0; i<v.size(); i++) cout << v[i] << " ";
    }
}
//C
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <vector>
typedef long long ll;
using namespace std;
const int N = 6e5+5;

int n, m, k, L, a[N], A[N], r[105], w[N], x[N], v[N];

int c[N];
inline void add(int p, int v) { //printf("add %d %d\n", p, v); cout << endl;
    for(; p<=n; p+=p&-p) c[p] += v;
}
inline int sum(int p) {
    int ans = 0;
    for(; p; p-=p&-p) ans += c[p];
    return ans;
}
inline void add(int l, int r, int v) {
    add(l, v);
    add(r+1, -v);
}

bool check(int mid) { //printf("check %d\n", mid);
    for(int i=1; i<=n; i++) a[i] = A[i];
    for(int p = 1; p <= m && w[p] <= mid; p++) a[x[p]] -= v[p];

    memset(c, 0, sizeof(c));
    for(int i=n; i>=1; i--) a[i] -= a[i-1];
    for(int i=1; i<=n; i++) add(i, a[i]);
    

    int ans = 0;
    for(int i=1; i<=n; i++) {
        int x = sum(i); //printf("hi %d %d\n", i, x);
        if(x < 1) add(i, i+k-1, 1-x), ans += 1-x; 
    } 
    //printf("ans %d\n", ans);
    return ans <= mid;
}
int main() {
    freopen("in", "r", stdin);
    ios::sync_with_stdio(false);

    cin >> n >> m >> k >> L;
    for(int i=1; i<=n; i++) cin >> A[i];
    for(int i=1; i<=L; i++) cin >> r[i];
    for(int i=1; i<=m; i++) cin >> w[i] >> x[i] >> v[i];
    int l = 0, r = 1e8, ans = 0;
    while(l <= r) { //printf("erfen %d %d\n", l, r);
        int mid = (l+r) >> 1;
        if(check(mid)) ans = mid, r = mid-1;
        else l = mid+1;
    }
    cout << ans;
}
posted @ 2018-07-16 11:17 Candy? 阅读(...) 评论(...) 编辑 收藏