zoukankan      html  css  js  c++  java
  • 寒 假 队 测 Round #1

    (65 + 0 + 0 + 0 = 65pts)
    菜得起飞
    (T1) 思维题,漏掉一个情况 + 打错一个情况
    (T2) 模拟打挂
    (T3) 博弈论白送的dp, (max)打成(min) , (70) to (0)
    (T4) 主席树,没动

    经验教训:

    1. 码力是真的差,2k的模拟都写不对.
    2. 小细节小错误太多.
    3. 写代码不一气呵成,思维不连贯.

    前三题题解不动了,等T4写出来写题解
    顺便 % cnyz(rk1).

    以后遇到自己不情愿写的题也得写.

    T4题解

    题目链接:middle,主席树好题

    题意简述:

    给定一个长度为(n)的序列(s)(q)个询问,
    每个询问包括(a,b,c,d)四个参数,求序列(s)(l)~(r)中可能的最大中位数,强制在线。
    其中(a) (leqslant) (l) (leqslant) (b)(c) (leqslant) (r) (leqslant) (d)

    题解

    关于中位数有个二分答案的技巧,
    二分一个值 (mid)
    大于等于(mid)的位置为(1),否则为(-1)
    求一下最大子序和,便知道(mid)是否可以更大,
    至此我们得到了一个做法:
    对于每个询问,二分(mid)(O(n))扫描得出最大子序和,
    并且保证子序左右端点满足(a) (leqslant) (l) (leqslant) (b)(c) (leqslant) (r) (leqslant) (d).
    时间复杂度(O(Qnlogn)),不能接受。
    我们转换一下思路,用数据结构维护最大子序和,线段树可以做到。
    我们先建好(n)棵线段树,这样查询复杂度降低到了(O(Qlog_2n))
    但是空间复杂度过高,预建时间也过高。
    我们自然的想到了专门为解决这两个问题而生的数据结构——可持久化线段树。
    最终的做法:

    1. 先将每个(s_i)排序,然后从小到大建主席树,如何求最大子序和还有维护的信息参见这个
      (~~~~)为什么排序呢?
      这样每一次建树才能继承上一次((-1)(1)值只浮动一个).
    2. 然后进行上述的二分做法
    3. 最大子序和求法:(b+1)(c-1)之间必须选,(a) ~ (b)选最大后缀,(c)~(d)选最大前缀。

    时间复杂度(O(NlogN+Qlog^2N)).

    Code:

    #include<bits/stdc++.h>
    using namespace std;
    const int N=2e4+10;
    int n,m,a[N],rk[N],b[N],cnt;
    int rt[N<<6],ls[N<<6],rs[N<<6];
    int lmx[N<<6],rmx[N<<6],sum[N<<6];
    bool cmp(int X,int Y){return a[X]<a[Y];}
    void updata(int p){
    	sum[p]=sum[ls[p]]+sum[rs[p]];
    	lmx[p]=max(lmx[ls[p]],sum[ls[p]]+lmx[rs[p]]);
    	rmx[p]=max(rmx[rs[p]],sum[rs[p]]+rmx[ls[p]]);
    }
    int build(int l,int r){
    	int p=++cnt;
    	if(l==r){
    		sum[p]=lmx[p]=rmx[p]=1;
    		return p;
    	}
    	int mid=l+r>>1;
    	ls[p]=build(l,mid);
    	rs[p]=build(mid+1,r);
    	updata(p);
    	return p;
    }
    int copy(int x,int y){
    	ls[x]=ls[y];
    	rs[x]=rs[y];
    	sum[x]=sum[y];
    	lmx[x]=lmx[y];
    	rmx[x]=rmx[y];
    }
    int insert(int pre,int l,int r,int x,int val){
    	int p=++cnt;
    	copy(p,pre);
    	if(l==r){
    		lmx[p]=rmx[p]=-1;
    		sum[p]+=val;
    		return p;
    	}
    	int mid=l+r>>1;
    	if(x<=mid)ls[p]=insert(ls[pre],l,mid,x,val);
    	else rs[p]=insert(rs[pre],mid+1,r,x,val);
    	updata(p);
    	return p;
    }
    int querysum(int p,int l,int r,int x,int y){
    	if(x<=l&&y>=r)return sum[p];
    	int mid=l+r>>1,ret=0;
    	if(x<=mid)ret+=querysum(ls[p],l,mid,x,y);
    	if(y>mid)ret+=querysum(rs[p],mid+1,r,x,y);
    	return ret;
    }
    int querylmx(int p,int l,int r,int x,int y){
    	if(x<=l&&y>=r)return lmx[p];
    	int mid=l+r>>1,ret;
    	if(x<=mid&&!(y>mid))ret=querylmx(ls[p],l,mid,x,y);
    	if(!(x<=mid)&&y>mid)ret=querylmx(rs[p],mid+1,r,x,y);
    	if(x<=mid&&y>mid)ret=max(querylmx(ls[p],l,mid,x,mid),querysum(ls[p],l,mid,x,mid)+querylmx(rs[p],mid+1,r,mid+1,y));
    	return ret;
    }
    int queryrmx(int p,int l,int r,int x,int y){
    	if(x<=l&&y>=r)return rmx[p];
    	int mid=l+r>>1,ret;
    	if(x<=mid&&!(y>mid))ret=queryrmx(ls[p],l,mid,x,y);
    	if(!(x<=mid)&&y>mid)ret=queryrmx(rs[p],mid+1,r,x,y);
    	if(x<=mid&&y>mid)ret=max(queryrmx(rs[p],mid+1,r,mid+1,y),querysum(rs[p],mid+1,r,mid+1,y)+queryrmx(ls[p],l,mid,x,mid));
    	return ret;
    }
    bool check(int t,int a,int b,int c,int d){
    	int sum=0;
    	if(b+1<=c-1)sum+=querysum(rt[t],1,n,b+1,c-1);
    	sum+=queryrmx(rt[t],1,n,a,b);
    	sum+=querylmx(rt[t],1,n,c,d);
    	return sum>=0;
    }
    int main(){
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++){
    		scanf("%d",&a[i]);
    		rk[i]=i;b[i]=a[i];
    	}
    	sort(b+1,b+n+1);
    	sort(rk+1,rk+n+1,cmp);
    	rt[1]=build(1,n);
    	for(int i=2;i<=n+1;i++)
    		rt[i]=insert(rt[i-1],1,n,rk[i-1],-2);
    	int T,Ans=0;
    	scanf("%d",&T);
    	while(T--){
    		int Q[4],A,B,C,D;
    		scanf("%d%d%d%d",&A,&B,&C,&D);
    		Q[0]=(A+Ans)%n;Q[1]=(B+Ans)%n;
    		Q[2]=(C+Ans)%n;Q[3]=(D+Ans)%n;
    		sort(Q,Q+4);
    		A=Q[0]+1;B=Q[1]+1;C=Q[2]+1;D=Q[3]+1;
    		int l=1,r=n;
    		while(l<=r){
    			int mid=l+r>>1;
    			if(check(mid,A,B,C,D))l=mid+1;
    			else r=mid-1;
    		}
    		Ans=b[r];
    		printf("%d
    ",Ans);
    	}
    	return 0;
    }
    
  • 相关阅读:
    持续集成-禅道
    nohup.out 日志切分
    Flannel 介绍及使用场景
    【Unity游戏开发】初探Unity动画优化
    fastHttp服务端处理请求的过程
    PHPExcel导出文件代码实现
    PHPExcel 1.8
    CKfinder 安装与使用
    Ckeditor的配置
    Ckeditor的使用
  • 原文地址:https://www.cnblogs.com/Xxhdjr/p/14337177.html
Copyright © 2011-2022 走看看