bzoj3110 K大数查询(整体二分+线段树)
发布时间:2020-12-14 03:26:51 所属栏目:大数据 来源:网络整理
导读:整体二分 ①将修改和查询看做是一条队列。 ②二分一个答案Mid,然后扫一下队列,用数据结构来依次(依照操作和询问顺序地)维护修改权值小于或等于Mid的修改对每个查询的贡献。 ③将数据结构清空。(注意时间复杂度) ④将修改和询问分成两份,其中 询问:如
整体二分①将修改和查询看做是一条队列。 程序#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 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |