• bzoj2527 [Poi2011]Meteors


    传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=2527

    【题解】

    整体二分思想,其实就是把一坨二分拿一起处理了。。。

    (事实上这题暴力好像。。不需要二分?)

    我们定义solve(l,r,al,ar)为当前二分区间为[l,r],在这个区间的公司为id[al..ar]

    那么我们每次把l..mid的操作做一下,然后依次判断每个公司是否满足了条件,满足就说明答案在[l,mid],归到左半区间;否则就说明答案在[mid+1,r],归到右半区间。

    归到某个区间实际上就是给al...ar重标号,使得有amid,al...amid被划分到左边,amid+1...ar被划分到右边。

    递归solve(l,mid,al,amid),solve(mid+1,r,amid+1,ar)即可。

    # include <stdio.h>
    # include <string.h>
    # include <iostream>
    # include <algorithm>
    // # include <bits/stdc++.h>
    
    using namespace std;
    
    typedef long long ll;
    typedef long double ld;
    typedef unsigned long long ull;
    const int M = 3e5 + 10;
    const int mod = 1e9+7;
    const int INF = 1e9;
    
    # define RG register
    # define ST static
    
    int n, m, Q;
    int bel[M]; 
    struct quest {
        int L, R, A;
        quest() {}
        quest(int L, int R, int A) : L(L), R(R), A(A) {}
    }q[M];
    
    int head[M], nxt[M], to[M], tot=0;
    inline void add(int u, int v) {
        ++tot; nxt[tot] = head[u]; head[u] = tot; to[tot] = v;
    }
    
    // 区间修改,单点查询 
    struct BIT {
        int n;
        ll c[M << 1]; 
        # define lb(x) (x&(-x))
        inline void set(int _n) {
            n = _n;
            memset(c, 0, sizeof c);
        }
        inline void edt(int x, ll d) {
            for (; x<=n; x+=lb(x)) c[x] += d;
        }
        inline void edt(int x, int y, ll d) {
            edt(x, d); edt(y+1, -d);
        }
        inline ll sum(int x) {
            ll ret = 0;
            for (; x; x-=lb(x)) ret += c[x];
            return ret;
        }
    }T;
    
    int a[M]; 
    ll s[M]; 
    int id[M], t1[M], t2[M]; 
    int ans[M];
    inline void solve(int l, int r, int al, int ar) {
        if(al > ar) return;
        if(l == r) {
            for (int i=al; i<=ar; ++i) ans[id[i]] = l;
            return ;
        }
        int mid = l+r>>1;
        for (int i=l; i<=mid; ++i) {
            if(q[i].L <= q[i].R) T.edt(q[i].L, q[i].R, q[i].A);
            else T.edt(1, q[i].R, q[i].A), T.edt(q[i].L, m, q[i].A);    
        }
        ll cur;    bool ok;
        int t1n, t2n, tn; t1n = t2n = 0;
        for (int i=al; i<=ar; ++i) {
            int x = id[i]; 
            ok = 0, cur = s[x];
            for (int j=head[x]; j; j=nxt[j]) {
                cur += T.sum(to[j]);
                if(cur >= a[x]) {
                    ok = 1;
                    break;
                }
            }
            if(ok) t1[++t1n] = x; 
            else t2[++t2n] = x, s[x] = cur; 
        }
        for (int i=l; i<=mid; ++i) {
            if(q[i].L <= q[i].R) T.edt(q[i].L, q[i].R, -q[i].A);
            else T.edt(1, q[i].R, -q[i].A), T.edt(q[i].L, m, -q[i].A);    
        }
        tn = al-1;
        for (int i=1; i<=t1n; ++i) id[++tn] = t1[i];
        t1n = tn;
        for (int i=1; i<=t2n; ++i) id[++tn] = t2[i];
        solve(l, mid, al, t1n);
        solve(mid+1, r, t1n+1, ar); 
    }
    
    int main() {
        cin >> n >> m; 
        for (int i=1; i<=m; ++i) {
            scanf("%d", &bel[i]); 
            add(bel[i], i); 
        }
        for (int i=1; i<=n; ++i) scanf("%d", &a[i]), id[i] = i; 
        cin >> Q; 
        for (int i=1; i<=Q; ++i) scanf("%d%d%d", &q[i].L, &q[i].R, &q[i].A);
        q[++Q] = quest(1, m, INF); 
        T.set(m+1); 
        solve(1, Q, 1, n); 
        for (int i=1; i<=n; ++i) 
            if(ans[i] == Q) puts("NIE");
            else printf("%d
    ", ans[i]); 
        return 0;
    }
    View Code
  • 相关阅读:
    英文词频统计
    字符串练习
    第八周
    第七周
    第五周
    第六周
    第三周
    第四周
    第二周
    第一周作业
  • 原文地址:https://www.cnblogs.com/galaxies/p/bzoj2527.html
Copyright © 2020-2023  润新知