加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

bzoj3110 K大数查询(整体二分+线段树)

发布时间:2020-12-14 03:26:51 所属栏目:大数据 来源:网络整理
导读:整体二分 ①将修改和查询看做是一条队列。 ②二分一个答案Mid,然后扫一下队列,用数据结构来依次(依照操作和询问顺序地)维护修改权值小于或等于Mid的修改对每个查询的贡献。 ③将数据结构清空。(注意时间复杂度) ④将修改和询问分成两份,其中 询问:如

整体二分

①将修改和查询看做是一条队列。
②二分一个答案Mid,然后扫一下队列,用数据结构来依次(依照操作和询问顺序地)维护修改权值小于或等于Mid的修改对每个查询的贡献。
③将数据结构清空。(注意时间复杂度)
④将修改和询问分成两份,其中
询问:如果问题答案小于或等于Mid,就放在队列1。
如果问题答案大于Mid,修改询问(减掉小于或等于Mid的问题对本答案的贡献),然后放在队列2。
修改:如果修改权值大于或等于Mid,就放在队列1,否则放在队列2。
⑤递归往下做。

程序

#include <iostream>
#include <algorithm>
#include <string.h>
#include <string>
#include <cmath>
#include <stdio.h>
#include <stdlib.h>
#include <vector>
using namespace std;

struct Query{
    int q,L,R,v,e;
}q[50100],p1[50100],p2[50100];
int T[201000],ad[201000],no[50100],ans[50100],n,m;

void down(int ro,int L,int R) {
    int mid=(L+R)>>1,zuo=ro<<1,you=zuo+1;
    T[zuo]+=(mid-L+1)*ad[ro];ad[zuo]+=ad[ro];
    T[you]+=(R-mid)*ad[ro];ad[you]+=ad[ro];
    ad[ro]=0;
}

void update(int ro,int R,int le,int ri) {
    if (le<=L&&R<=ri) {
        T[ro]+=R-L+1; ad[ro]++;
        return ;
    }
    if (L>ri||R<le) return;
    if (ad[ro]) down(ro,R);
    int mid=(L+R)>>1,you=zuo+1;
    update(zuo,mid,le,ri);update(you,mid+1,ri);
    T[ro]=T[zuo]+T[you];
}

int query(int ro,int ri) {
    if (le<=L&&R<=ri) return T[ro];
    if (L>ri||R<le) return 0;
    if (ad[ro]) down(ro,you=zuo+1;
    return query(zuo,ri)+query(you,ri);
}

void build(int ro,int R) {
    if (T[ro]==0) return;
    if (L==R) {T[ro]=ad[ro]=0;return;}
    int mid=(L+R)>>1,you=zuo+1;
    build(zuo,mid);build(you,R);
    T[ro]=ad[ro]=0;
}

void solve(int he,int ta,int R) {
    if (ta<he) return;
    if (L==R) {
        for (int i=he;i<=ta;i++) 
        if (q[i].q==2)
        ans[q[i].e]=L;
        return ;
    }
    int mid=L+R>>1;
    for (int i=he;i<=ta;i++) {
        if (q[i].q==1&&q[i].v<=mid)
            update(1,1,q[i].L,q[i].R);
        else if (q[i].q==2)
            no[i]=query(1,q[i].R);
    }
    build(1,n);
    int cnt1=0,cnt2=0;
    for (int i=he;i<=ta;i++)
        if (q[i].q==1) 
            if (q[i].v<=mid) p1[++cnt1]=q[i];
            else p2[++cnt2]=q[i];
        else if (no[i]>=q[i].v) p1[++cnt1]=q[i];
            else {q[i].v-=no[i];p2[++cnt2]=q[i];}

    for (int i=1;i<=cnt1;i++) q[i+he-1]=p1[i];
    for (int i=1;i<=cnt2;i++) q[he+cnt1+i-1]=p2[i];

    solve(he,he+cnt1-1,mid);
    solve(he+cnt1,ta,R);
}

int main(){
    scanf("%d%d",&n,&m);
    for (int i=1;i<=m;i++){
        int x,y,z,w;
        scanf("%d%d%d%d",&x,&y,&z,&w);
        if (x==1)w=-w;
        q[i] = (Query) {x,w,i};
    }
    for (int i=1;i<=m;i++) ans[i]=-60000;
    solve(1,m,-50100,50100);
    for (int i=1;i<=m;i++)
    if (ans[i]!=-60000) {
        if (ans[i]==1) printf("50000n");
        else printf("%dn",-ans[i]);
    }

    return 0;
}

推荐看

http://www.cnblogs.com/dirge/p/5810855.html

Jeanne d’Arc镇楼

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读