Luogu3527 POI2011 Meteors 整体二分、树状数组、差分

传送门



比较板子的整体二分题目,时限有点紧注意常数

整体二分的过程中将时间在\([l,mid]\)之间的流星使用树状数组+差分进行维护,然后对所有国家查看一遍并分好类,递归下去,记得消除答案在\([mid+1,r]\)的询问中时间在\([l,mid]\)的流星操作的贡献

注意:可能存在某一段时间某一个国家的流星数量超过long long范围,应该当某个时候国家流星量和大于等于国家需求值时直接退出,这样可以避免这个问题。

#include<bits/stdc++.h>
#define INF 0x7fffffff
#define lowbit(x) ((x) & -(x))
using namespace std;

inline int read(){
    int a = 0;
    char c = getchar();
    while(!isdigit(c))
        c = getchar();
    while(isdigit(c)){
        a = a * 10 + c - 48;
        c = getchar();
    }
    return a;
}

const int MAXN = 3e5 + 10;
vector < int > bel[MAXN];
long long BIT[MAXN];
int qry[MAXN][2] , tp[2][MAXN][2] , mod[MAXN][3] , ans[MAXN];
int N , M , K;

inline void add(int p , int num){
    while(p <= M){
        BIT[p] += num;
        p += lowbit(p);
    }
}

inline long long get(int p){
    long long sum = 0;
    while(sum < 1e9 && p){
        sum += BIT[p];
        p -= lowbit(p);
    }
    return sum;
}

void solve(int ql , int qr , int l , int r){
    if(qr < ql)
        return;
    if(l == r){
        for(int i = ql ; i <= qr ; ++i)
            ans[qry[i][0]] = l;
        return;
    }
    int mid = (l + r) >> 1 , p0 = 0 , p1 = 0;
    for(int i = l ; i <= mid ; ++i){
        add(mod[i][1] + 1 , -mod[i][2]);
        add(mod[i][0] , mod[i][2]);
        if(mod[i][0] > mod[i][1])
            add(1 , mod[i][2]);
    }
    for(int i = ql ; i <= qr ; ++i){
        long long sum = 0;
        for(int j = 0 ; j < bel[qry[i][0]].size() && sum < qry[i][1] ; ++j)
            sum += get(bel[qry[i][0]][j]);
        if(sum >= qry[i][1]){
            tp[0][++p0][0] = qry[i][0];
            tp[0][p0][1] = qry[i][1];
        }
        else{
            tp[1][++p1][0] = qry[i][0];
            tp[1][p1][1] = qry[i][1] - sum;
        }
    }
    memcpy(qry + ql , tp[0] + 1 , sizeof(int) * p0 * 2);
    memcpy(qry + ql + p0 , tp[1] + 1 , sizeof(int) * p1 * 2);
    for(int i = l ; i <= mid ; ++i){
        add(mod[i][1] + 1 , mod[i][2]);
        add(mod[i][0] , -mod[i][2]);
        if(mod[i][0] > mod[i][1])
            add(1 , -mod[i][2]);
    }
    solve(ql , ql + p0 - 1 , l , mid);
    solve(ql + p0 , qr , mid + 1 , r);
}

signed main(){
    N = read();
    M = read();
    for(int i = 1 ; i <= M ; ++i)
        bel[read()].push_back(i);
    for(int i = 1 ; i <= N ; ++i){
        qry[i][0] = i;
        qry[i][1] = read();
    }
    K = read();
    for(int i = 1 ; i <= K ; ++i){
        mod[i][0] = read();
        mod[i][1] = read();
        mod[i][2] = read();
    }
    solve(1 , N , 1 , K + 1);
    for(int i = 1 ; i <= N ; ++i)
        if(ans[i] == K + 1)
            puts("NIE");
        else
            printf("%d\n" , ans[i]);
    return 0;
}

原文地址:https://www.cnblogs.com/Itst/p/10228264.html

时间: 2024-08-11 23:22:43

Luogu3527 POI2011 Meteors 整体二分、树状数组、差分的相关文章

【bzoj2527】[Poi2011]Meteors 整体二分+树状数组

题目描述 有N个成员国.现在它发现了一颗新的星球,这颗星球的轨道被分为M份(第M份和第1份相邻),第i份上有第Ai个国家的太空站. 这个星球经常会下陨石雨.BIU已经预测了接下来K场陨石雨的情况.BIU的第i个成员国希望能够收集Pi单位的陨石样本.你的任务是判断对于每个国家,它需要在第几次陨石雨之后,才能收集足够的陨石. 输入 第一行是两个数N,M. 第二行有M个数,第i个数Oi表示第i段轨道上有第Oi个国家的太空站. 第三行有N个数,第i个数Pi表示第i个国家希望收集的陨石数量. 第四行有一个

【BZOJ-2527】Meteors 整体二分 + 树状数组

2527: [Poi2011]Meteors Time Limit: 60 Sec  Memory Limit: 128 MBSubmit: 831  Solved: 306[Submit][Status][Discuss] Description Byteotian Interstellar Union (BIU) has recently discovered a new planet in a nearby galaxy. The planet is unsuitable for colo

bzoj 2527 Meteors - 整体二分 - 树状数组

Description Byteotian Interstellar Union (BIU) has recently discovered a new planet in a nearby galaxy. The planet is unsuitable for colonisation due to strange meteor showers, which on the other hand make it an exceptionally interesting object of st

【BZOJ3110】【整体二分+树状数组区间修改/线段树】K大数查询

Description 有N个位置,M个操作.操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c 如果是2 a b c形式,表示询问从第a个位置到第b个位置,第C大的数是多少. Input 第一行N,M 接下来M行,每行形如1 a b c或2 a b c Output 输出每个询问的结果 Sample Input 2 5 1 1 2 1 1 1 2 2 2 1 1 2 2 1 1 1 2 1 2 3 Sample Output 1 2 1 HINT

【bzoj3110】[Zjoi2013]K大数查询 整体二分+树状数组区间修改

题目描述 有N个位置,M个操作.操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c.如果是2 a b c形式,表示询问从第a个位置到第b个位置,第C大的数是多少. 输入 第一行N,M接下来M行,每行形如1 a b c或2 a b c 输出 输出每个询问的结果 样例输入 2 5 1 1 2 1 1 1 2 2 2 1 1 2 2 1 1 1 2 1 2 3 样例输出 1 2 1 题解 整体二分+树状数组区间修改 当年naive的树套树题解 前两天由于要

luogu3242 接水果 (整体二分+树状数组)

考虑整体二分,问题就变成了每个(水果)路径有多少个满足条件(权值)的(盘子)子路径 考虑一个盘子(a,b)表示两端点(不妨设dfn[a]<dfn[b]),那么他能接到的水果(u,v)一定满足(不妨设dfn[u]<dfn[v]): 1.如果a是b的祖先,则u在(a的在(b,a)链上的孩子)这个子树外,v在b子树内 2.否则,u在a的子树内,v在b的子树内 那么把一个水果(a,b)看成是一个二维点(dfn[a],dfn[b]),对于每个盘子,就是做一个二维区间+1 差分以后变成一个二维数点问题,可

【POJ2104】【整体二分+树状数组】区间第k大

Description You are working for Macrohard company in data structures department. After failing your previous task about key insertion you were asked to write a new data structure that would be able to return quickly k-th order statistics in the array

BZOJ_3110_[Zjoi2013]K大数查询_整体二分+树状数组

Description 有N个位置,M个操作.操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c 如果是2 a b c形式,表示询问从第a个位置到第b个位置,第C大的数是多少. Input 第一行N,M 接下来M行,每行形如1 a b c或2 a b c Output 输出每个询问的结果 Sample Input 2 5 1 1 2 1 1 1 2 2 2 1 1 2 2 1 1 1 2 1 2 3 Sample Output 1 2 1 solve

11525 - Permutation(二分+树状数组)

题目链接:点击打开链接 题意:从1~k的所有排列中找到第n个排列, n由公式给出. 思路:可以发现, 这个公式就是康托展开公式(康托展开百科:点击打开链接). 那么s[i]的意思就是i个数中当前数排在第几. 如此, 可以用二分+树状数组快速求解, 和一道BC题目神似. 细节参见代码: #include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #include<st