poj2104(整體二分)

題目鏈接:http://poj.org/problem?id=2104

思路:這題是靜態的完全可以不用整體二分,我是拿來當板子題寫的

https://blog.csdn.net/wu_tongtong/article/details/78823783

所謂整體二分,需要數據結構題滿足以下性質: 
1. 詢問的答案具有可二分性 
2. 修改對判定答案的貢獻相對獨立,修改之間互不影響效果 
3. 修改如果對判定答案有貢獻,則貢獻爲一確定的與判定標準無關的值 
4. 貢獻滿足交換律,結合律,具有可加性 
5. 題目允許離線操作

詢問的答案有可二分性質顯然是前提,我們發現,因爲修改對判定標準的貢獻相對獨立,且貢獻的值(如果有的話)與判定標準無關,所以如果我們已經計算過某一些修改對詢問的貢獻,那麼這個貢獻永遠不會改變,我們沒有必要當判定標準改變時再次計算這部分修改的貢獻,只要記錄下當前的總貢獻,再進一步二分時,直接加上新的貢獻即可 
這樣的話,我們發現,處理的複雜度可以不再與序列總長度直接相關了,而可能只與當前待處理序列的長度相關
 

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <cctype>
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#include <queue>
#include <map>
#include <set>
#include <sstream>
#include<iomanip>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll inff = 0x3f3f3f3f3f3f3f3f;
#define FOR(i,a,b) for(int i(a);i<=(b);++i)
#define FOL(i,a,b) for(int i(a);i>=(b);--i)
#define REW(a,b) memset(a,b,sizeof(a))
#define inf int(0x3f3f3f3f)
#define si(a) scanf("%d",&a)
#define sl(a) scanf("%I64d",&a)
#define sd(a) scanf("%lf",&a)
#define ss(a) scanf("%s",a)
#define mod int(1e9+7)
#define lc (d<<1)
#define rc (d<<1|1)
#define P pair<int,int>
#define pi acos(-1)
int n,m,a[100008],qw,x,y,z,ans[200008];
struct as{
int ty,pos,x,y,k;}q[200000],q1[200000],q2[200000];
int sum(int x)
{
    int s=0;
    while(x>0) s+=a[x],x-=x&-x;
    return s;
}
void add(int x,int y) {while(x<=n) a[x]+=y,x+=x&-x;}
void solve(int l, int r, int L, int R)
{
    if(l>r||L>R) return;
    if(l==r)
    {
        for(int i=L;i<=R;i++) if(q[i].ty) ans[q[i].pos]=l;
        return;
    }
    int mid=(l+r)>>1,cnt1=0,cnt2=0;
    for(int i=L;i<=R;i++)
    if(q[i].ty)
    {
        int tmp=sum(q[i].y)-sum(q[i].x-1);
        if(tmp>=q[i].k) q1[++cnt1]=q[i];
        else q[i].k-=tmp, q2[++cnt2]=q[i];
    }
    else
    {
        if(q[i].x<=mid) add(q[i].pos,q[i].y),q1[++cnt1]=q[i];
        else q2[++cnt2]=q[i];
    }
    for(int i=1;i<=cnt1;i++) if(!q1[i].ty) add(q1[i].pos,-q1[i].y);
    for(int i=1;i<=cnt1;i++) q[L+i-1]=q1[i];
    for(int i=1;i<=cnt2;i++) q[L+cnt1+i-1]=q2[i];
    solve(l,mid,L,L+cnt1-1); solve(mid+1,r,L+cnt1,R);
}
int main()
{
    cin.tie(0);
    cout.tie(0);
    cin>>n>>m;
    FOR(i,1,n) si(x),q[++qw]=as{0,i,x,1,0};
    FOR(i,1,m)
    {
        si(x),si(y),si(z);
        q[++qw]=as{1,i,x,y,z};
    }
    solve(-inf,inf,1,qw);
    FOR(i,1,m) printf("%d\n",ans[i]);
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章