[Poi2011] Meteors(从不知所措到整体二分)

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 study.

The member states of BIU have already placed space stations close to the planet‘s orbit. The stations‘ goal is to take samples of the rocks flying by. The BIU Commission has partitioned the orbit into  sectors, numbered from  to , where the sectors  and  are adjacent. In each sector there is a single space station, belonging to one of the  member states.

Each state has declared a number of meteor samples it intends to gather before the mission ends. Your task is to determine, for each state, when it can stop taking samples, based on the meter shower predictions for the years to come.

Input

The first line of the standard input gives two integers,  and  (), separated by a single space, that denote, respectively, the number of BIU member states and the number of sectors the orbit has been partitioned into.

In the second line there are  integers  (), separated by single spaces, that denote the states owning stations in successive sectors.

In the third line there are  integers  (), separated by single spaces, that denote the numbers of meteor samples that the successive states intend to gather.

In the fourth line there is a single integer  () that denotes the number of meteor showers predictions. The following  lines specify the (predicted) meteor showers chronologically. The -th of these lines holds three integers  (separated by single spaces), which denote that a meteor shower is expected in sectors  (if ) or sectors  (if ), which should provide each station in those sectors with  meteor samples ().

Output

Your program should print  lines on the standard output. The -th of them should contain a single integer , denoting the number of shower after which the stations belonging to the -th state are expected to gather at least  samples, or the word NIE (Polish for no) if that state is not expected to gather enough samples in the foreseeable future.

Example

For the input data:

3 5
1 3 2 1 3
10 5 7
3
4 2 4
1 3 1
3 5 2

the correct result is:

3
NIE
1

题意:

n个国家,m个收集站,每个收集站分别归属于某个国家,一共又k颗流星,问每个国家再第几颗流星经过可以搜集够自己需要的流星need[i]。

先谈谈自己的感受。

普通二分过程([L,R]+一个询问X):二分[L,mid]或者二分[mid+1,R]。最后L==R时得到了一个询问的答案X。

整体二分过程([L,R]+一群询问X):部分询问(集合A)需要二分[L,mid](假设叫左二分),一些询问(集合B)需要二分[mid+1,R](右二分)。这个时候把属于左二分是一起左二分,属于有二分的一起右二分。 当L==R时得到了当前集合的答案,其中集合X=集合A+集合B。

对于整体效率的分析:

假设二分solve(X,L,R)表示集合X的答案在[L,R]间(L,R是由上一层二分判定缩小的范围,初始L=1,R=m,X为1到n的集合)。

按照上面整体二分的过程,solve(X,L,R)继续分解为solve(A,L,mid)和solve(B,mid+1,R)两部分;前面一部分是mid的时候,A集合满足条件need[],答案范围缩小为[L,mid];同理,B集合不满足条件need[],答案范围缩小到[mid+1,R]。

所以,若最开始的集合X=(1,2,3,...n)最后分解为了g个集合(1<=g<=m,m为操作数量,此题的流星数量),

每一个二分复杂度为O(qlgn),q为一个常数,大小取决于题目,总的效率为O(g*qlgn)<O(m*qlgn)。如果最后集合g,q不会太大,整体二分就行得通。而g取决于数据,q取决于算法。

综上,大概知道什么是整体二分了。具体针对这道题:

(抄袭的代码,From victorywonder,现在主要是学习思想,首先的化,多做几个题再整理)。

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
using namespace std;
typedef long long ll;
typedef double D;
typedef pair<int,int> pr;
const int infi=1000000010;
const int N=500010;
const int M=2000100;
struct node{int x,y,z;}p[N];
int n,m,k,c[N],id[N],ans[N];
int g[N],to[N],nxt[N],tot;
int tol[N],tor[N];
ll h[N],tmp[N],cur[N];
void add(int pos,int x) {while (pos<=m) h[pos]+=x,pos+=(pos&-pos);}
void adddt(int x,int y,int z) {add(x,z); add(y+1,-z);}
ll sum(int pos) {ll t=0; while (pos>0) t+=h[pos],pos-=(pos&-pos);return t;}
void addop(int x,int y,int z,int i) {p[i].x=x; p[i].y=y; p[i].z=z;}//第i颗流星
void addpt(int x,int y) {to[++tot]=y; nxt[tot]=g[x]; g[x]=tot;}//第x个国家,拥有的收集站。
void solve(int head,int tail,int l,int r) { //id [head到tail]的队列答案在[l,r]中
    if (head>tail) return;
    int i,k,x,mid=(l+r)>>1,lnum=0,rnum=0;
    if(l==r) {
        for (i=head;i<=tail;i++) ans[id[i]]=l;
        return;
    }
    for(i=l;i<=mid;i++) {//试探左半截。
        if (p[i].x<=p[i].y) adddt(p[i].x,p[i].y,p[i].z);//加入树状数组
        else adddt(p[i].x,m,p[i].z),adddt(1,p[i].y,p[i].z);//由于是个环。
    }
    for(i=head;i<=tail;i++) {
        tmp[id[i]]=0;
        for (k=g[id[i]];k;k=nxt[k]) {//第id[i]个国家的每一个站。
            tmp[id[i]]+=sum(to[k]);
            if (tmp[id[i]]+cur[id[i]]>c[id[i]]) break;
        }
        if (cur[id[i]]+tmp[id[i]]>=c[id[i]]) tol[++lnum]=id[i];
        else tor[++rnum]=id[i],cur[id[i]]+=tmp[id[i]];
    }
    for (i=l;i<=mid;i++) {//减回去。效果就是memset(h,0,sizeof(h)),但是memset太浪费了;
        if (p[i].x<=p[i].y) adddt(p[i].x,p[i].y,-p[i].z);
        else adddt(p[i].x,m,-p[i].z),adddt(1,p[i].y,-p[i].z);
    }
    for (i=0;i<lnum;i++) id[head+i]=tol[i+1];
    for (i=0;i<rnum;i++) id[head+lnum+i]=tor[i+1];
    solve(head,head+lnum-1,l,mid);
    solve(head+lnum,tail,mid+1,r);
}
int main() {
    int i,x,y,z;
    scanf("%d%d",&n,&m);
    for (i=1;i<=m;i++) {
        scanf("%d",&x);
        addpt(x,i);
    }
    for (i=1;i<=n;i++) {
        scanf("%d",&c[i]);
        id[i]=i;
    }
    scanf("%d",&k);
    for (i=1;i<=k;i++) {
        scanf("%d%d%d",&x,&y,&z);
        addop(x,y,z,i);
    }
    addop(1,m,infi,++k);
    solve(1,n,1,k);
    for (i=1;i<=n;i++) if (ans[i]!=k) printf("%d\n",ans[i]);
    else puts("NIE");
    return 0;
}

原文地址:https://www.cnblogs.com/hua-dong/p/8193927.html

时间: 2024-10-17 08:54:31

[Poi2011] Meteors(从不知所措到整体二分)的相关文章

整体二分-BZOJ2527【poi2011】meteors

2527: [Poi2011]Meteors Time Limit: 60 Sec Memory Limit: 128 MB Submit: 405 Solved: 160 [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 [Poi2011]Meteors(整体二分)

[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2527 [题目大意] 有N个成员国.现在它发现了一颗新的星球, 这颗星球的轨道被分为M份(第M份和第1份相邻),第i份上有第Ai个国家的太空站. 这个星球经常会下陨石雨.BIU已经预测了接下来K场陨石雨的情况. BIU的第i个成员国希望能够收集Pi单位的陨石样本. 你的任务是判断对于每个国家,它需要在第几次陨石雨之后,才能收集足够的陨石. [题解] 如果枚举每场陨石雨,树状数组查询每个

【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 Poi2011 Meteors 整体二分+线段树 / 可持久化线段树(MLE)

题目大意:给定一个环,每个节点有一个所属国家,k次事件,每次对[l,r]区间上的每个点点权加上一个值,求每个国家最早多少次操作之后所有点的点权和能达到一个值 首先我们考虑暴力想法 对于每个国家分开讨论 二分操作次数 但是这样每次Judge的时候我们要模拟1~mid所有的操作 浪费在这里的复杂度实在太大 这样做每个国家需要模拟O(klogk)次操作 时间复杂度O(nklogk) TLE 我们需要对浪费在这里的复杂度做一些改进 1.可持久化线段树(MLE) 每次二分一个mid之后 我们要找到mid次

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

传送门 比较板子的整体二分题目,时限有点紧注意常数 整体二分的过程中将时间在\([l,mid]\)之间的流星使用树状数组+差分进行维护,然后对所有国家查看一遍并分好类,递归下去,记得消除答案在\([mid+1,r]\)的询问中时间在\([l,mid]\)的流星操作的贡献 注意:可能存在某一段时间某一个国家的流星数量超过long long范围,应该当某个时候国家流星量和大于等于国家需求值时直接退出,这样可以避免这个问题. #include<bits/stdc++.h> #define INF 0

【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

Luogu P3527 [POI2011]MET-Meteors 整体二分

思路:整体二分 提交:4次 错因:树状数组开的$int$ 题解: 二分操作序列,将仅用$[l,md]$即可满足要求的国家递归到左半边,将仅用$[l,md]$不能满足要求的国家,把他们的要求去掉左半边的贡献,递归到右半边. 具体来说,开一个以空间站为下标的树状数组(把环展成链),区间加单点求和转化为差分和前缀和,依次加入$[l,md]$中的所有操作区间: 然后每个国家枚举自己的所有空间站,计算贡献,判断前$[l,md]$是否满足,来决定向左右递归的方向. #include<iostream> #

【BZOJ 2527】 [Poi2011]Meteors

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