1. 程式人生 > >[Poi2011] Meteors(從不知所措到整體二分)

[Poi2011] Meteors(從不知所措到整體二分)

adc range poi discover text bae pair sts cab

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;
}

[Poi2011] Meteors(從不知所措到整體二分)