zoukankan      html  css  js  c++  java
  • bzoj2653: middle

    传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=2653

    思路:陈老师的题

    可持久化线段树的又一种应用

    对于每次询问,二分答案

    我们怎么知道它是大于中位数还是小于中位数呢?

    我们把每个小于它的赋成-1,大于等于赋为1

    查询左端点在[a,b]右端点在[c,d]的区间的最大子段和

    若小于0,则偏大,大于等于0,偏小或者正好

    我们建立n棵权值线段树,从小到大把该数对应位置从1变为-1,维护左起/右起最大字段和,区间sum

    但空间开不下,改成可持久化版即可

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    const int maxn=20010,maxt=400010,inf=0x7f7f7f7f;
    using namespace std;
    int n,Q,lastans=0,q[4],root[maxn];char ch;
    void read(int &x){
    	for (ch=getchar();!isdigit(ch);ch=getchar());
    	for (x=0;isdigit(ch);ch=getchar()) x=x*10+ch-'0';
    }
    
    struct data{
    	int v,id;
    	void init(int i){read(v),id=i;}
    }seq[maxn];
    bool cmp(data a,data b){return a.v<b.v;}
    struct node{
    	int lmax,rmax,sum;
    	void assign(int v){lmax=rmax=sum=v;}
    };
    
    node merge(const node &a,const node &b){
    	node res;
    	res.lmax=max(a.lmax,a.sum+b.lmax);
    	res.rmax=max(b.rmax,b.sum+a.rmax);
    	res.sum=a.sum+b.sum;
    	return res;
    }
    
    struct Tsegment{
    	#define ls ch[p][0]
    	#define rs ch[p][1]
    	#define mid ((l+r)>>1)
    	node t[maxt];int tot,ch[maxt][2];
    	inline void update(int p){t[p]=merge(t[ls],t[rs]);}
    	void build(int &p,int l,int r){
    		p=++tot;
    		//printf("p=%d l=%d r=%d
    ",p,l,r);
    		if (l==r){t[p].assign(1);return;}
    		build(ls,l,mid),build(rs,mid+1,r),update(p);
    		//printf("p=%d ls=%d rs=%d
    ",p,ls,rs);
    	}
    	void modify(int pre,int &p,int l,int r,int x){
    		p=++tot;//printf("%d %d %d %d %d
    ",pre,p,l,r,x);
    		if (l==r){t[p].assign(-1);return;}
    		if (x<=mid) rs=ch[pre][1],modify(ch[pre][0],ls,l,mid,x);
    		else ls=ch[pre][0],modify(ch[pre][1],rs,mid+1,r,x);
    		update(p);
    	}
    	
    	node query(int p,int l,int r,int a,int b){
    		if (l==a&&r==b) return t[p];
    		if (b<=mid) return query(ls,l,mid,a,b);
    		else if (a>mid) return query(rs,mid+1,r,a,b);
    		else return merge(query(ls,l,mid,a,mid),query(rs,mid+1,r,mid+1,b));
    	}
    	node query(int ver,int l,int r){if (l>r) return (node){-inf,-inf,0};return query(root[ver],1,n,l,r);}
    	void modify(int ver,int pos){modify(root[ver-1],root[ver],1,n,pos);}
    	#undef mid
    }T;
    
    bool check(int id){
    	return T.query(id,q[0],q[1]).rmax+T.query(id,q[1]+1,q[2]-1).sum+T.query(id,q[2],q[3]).lmax>=0;
    }
    
    void init(){
    	scanf("%d",&n);
    	for (int i=1;i<=n;i++) seq[i].init(i);
    	sort(seq+1,seq+1+n,cmp);
    	T.build(root[1],1,n);
    	for (int i=1;i<=n;i++)T.modify(i+1,seq[i].id);// printf("root=%d
    ",root[i]),
    }
    
    void getans(){
    	int l=1,r=n,mid=(l+r)>>1,ans=1;
    	while (l<=r){
    		if (check(mid)) ans=mid,l=mid+1;
    		else r=mid-1;
    		mid=(l+r)>>1;
    	}
    	printf("%d
    ",seq[ans].v);
    	lastans=seq[ans].v;
    }
    
    void work(){
    	scanf("%d",&Q);
    	for (int i=1;i<=Q;i++){
    		for (int j=0;j<4;j++)
    			read(q[j]),q[j]=(q[j]+lastans)%n+1;
    		sort(q,q+4);getans();
    		//for (int j=0;j<4;j++) printf("j=%d %d
    ",j,q[j]);
    		
    	}
    }
    
    int main(){
    	init(),work();
    	return 0;
    }


  • 相关阅读:
    LightOJ 1132 Summing up Powers(矩阵快速幂)
    hdu 3804 Query on a tree (树链剖分+线段树)
    LightOJ 1052 String Growth && uva 12045 Fun with Strings (矩阵快速幂)
    uva 12304 2D Geometry 110 in 1! (Geometry)
    LA 3263 That Nice Euler Circuit (2D Geometry)
    2013 SCAUCPC Summary
    poj 3321 Apple Tree (Binary Index Tree)
    uva 11796 Dog Distance (几何+模拟)
    uva 11178 Morley's Theorem (2D Geometry)
    动手动脑
  • 原文地址:https://www.cnblogs.com/thythy/p/5493630.html
Copyright © 2011-2022 走看看