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\n", ans[i]); 
    return 0;
}
View Code

 

posted @ 2017-06-04 21:35  Galaxies  阅读(193)  评论(0编辑  收藏  举报