• cf gym102901K The Stream of Corning 2 离线+bit


    题目链接
    大意:给你一系列操作
    1:l,val,rl,val,r,添加一个val[l,r]val存在于[l,r]区间。
    2. index,kindex,k问你存在于 indexindex这个位置的第kk小数,若不存在输出-1;
    思路:我们可以将1操作的区间两个端点拆开和2操作的时间放在一个数组中进行排序(小的优先)。用opt标记这是左端点还是右端点还是询问。
    然后我们将所有的值进行离散化,(1操作中的val,2操作中的index)。
    然后遍历已经排好序的所有操作。若当前是左端点,则在树状数组中加入这个val。若是右端点则删除。若是询问操作的话,先特判是否存在,存在的话则二分查找位置记录答案。
    细节见代码

    #include<bits/stdc++.h>
    
    #define LL long long
    #define fi first
    #define se second
    #define mp make_pair
    #define pb push_back
    
    using namespace std;
    
    LL gcd(LL a,LL b){return b?gcd(b,a%b):a;}
    LL lcm(LL a,LL b){return a/gcd(a,b)*b;}
    LL powmod(LL a,LL b,LL MOD){LL ans=1;while(b){if(b%2)ans=ans*a%MOD;a=a*a%MOD;b/=2;}return ans;}
    const int N = 2e5 +11;
    int t,n;
    struct uzi
    {
    	int opt,x,val,id;
    	bool operator <(const uzi & t)const{
    		if(x==t.x)return id<t.id;
    		return x<t.x;
    	}
    }p[N];
    int dx=0,dy=0,dz=0;
    int c[N],a[N],ans[N],len;
    int add(int now,int x){
    	for(int i=now;i<=len;i+=(i&(-i)))c[i]+=x;
    }
    int que(int now){
    	int sum=0;
    	for(int i=now;i;i-=(i&(-i)))sum+=c[i];
    	return sum;
    }
    int get(int sum){
    	int l=1,r=len,ans=-1;
    	while(l<=r){
    		int mid=l+r>>1;
    		if(que(mid)>=sum)ans=mid,r=mid-1;
    		else l=mid+1;
    	}
    	return ans;
    }
    int now;
    int main(){
    	for(scanf("%d",&t);t;t--){
    		scanf("%d",&n);
    		dx=dy=dz=0;
    		memset(c,0,sizeof c);
    		memset(ans,0,sizeof ans);
    		for(int i=1;i<=n;i++){
    			int opt,x,y,z;
    			scanf("%d%d%d",&opt,&x,&y);
    			a[++dz]=y;
    			if(opt==1){
    				scanf("%d",&z);
    				p[++dx]={1,x,y,i};
    				p[++dx]={-1,z+1,y,i};
    			}else p[++dx]={2,x,y,i};
    		}
    		sort(a+1,a+1+dz);
    		len=unique(a+1,a+1+dz)-a-1;
    		for(int i=1;i<=dx;i++)p[i].val=lower_bound(a+1,a+1+len,p[i].val)-a;
    		sort(p+1,p+1+dx);
    		for(int i=1;i<=dx;i++){
    			if(p[i].opt!=2){
    				add(p[i].val,p[i].opt);
    			}else{
    				if(que(len)<p[i].val)ans[i]=-1;
    				else ans[i]=get(p[i].val);
    			}
    		}
    		printf("Case %d:
    ",++now );
    		for(int i=1;i<=dx;i++){
    			if(!ans[i])continue;
    			if(ans[i]==-1)printf("-1
    ");
    			else printf("%d
    ",a[ans[i]] );
    		}
    	}
    	return 0;
    }
    

    又加了一个主席树的在线版本。
    用优先队列维护右端点,在需要查询的时候更新已经消失的val。然后直接主席树查询第k小即可。

    #include <bits/stdc++.h>
    #define LL long long
    #define fi first
    #define se second
    #define mp make_pair
    #define pb push_back
    
    using namespace std;
    
    LL gcd(LL a,LL b){return b?gcd(b,a%b):a;}
    LL lcm(LL a,LL b){return a/gcd(a,b)*b;}
    LL powmod(LL a,LL b,LL MOD){LL ans=1;while(b){if(b%2)ans=ans*a%MOD;a=a*a%MOD;b/=2;}return ans;}
    const int N = 1e5 +11;
    const int M =1e6;
    int n,m;
    struct uzi
    {
    	int sum,l,r;
    }T[N*40];
    int now,a[N],b[N],t[N];
    void update(int l,int r,int &x,int y,int pos,int val){
    	x=++now;
    	T[++x]=T[y];T[x].sum+=val;
    	if(l==r)return ;
    	int mid=l+r>>1;
    	if(mid>=pos)update(l,mid,T[x].l,T[y].l,pos,val);
    	else update(mid+1,r,T[x].r,T[y].r,pos,val);
    }
    int get(int now,int l,int r,int k){
    	if(T[now].sum<k)return -1;
    	if(l==r)return l;
    	int mid=l+r>>1;
    	if(T[T[now].l].sum>=k)return get(T[now].l,l,mid,k);
    	else return get(T[now].r,mid+1,r,k-T[T[now].l].sum);
    }
    int ab,noa;
    int main(){
    	for(scanf("%d",&ab);ab;ab--){
    		printf("Case %d:
    ",++noa );
    		scanf("%d",&n);
    		int cnt=0;
    		now=0;
    		priority_queue<pair<int,int> >q;
    		for(int i=1;i<=n;i++){
    			int opt,l,r,z,val;
    			scanf("%d%d%d",&opt,&l,&val);
    			if(opt==1){
    				scanf("%d",&r);
    				update(1,M+1,cnt,cnt,val,1);
    				q.push({-r,val});
    			}else{
    				while(!q.empty()&&-q.top().fi<l){
    					update(1,M+1,cnt,cnt,q.top().se,-1);
    					q.pop();
    				}
    				printf("%d
    ",get(cnt,1,M+1,val));
    			}
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    SPOJ913 Query on a tree II
    SPOJ375 Query on a tree
    HDU4348 To the moon
    Bzoj2753 [SCOI2012]滑雪与时间胶囊
    HDU4612 Warm up
    Uva11374 Airport Express
    Uva1624 Knots
    DevExpress的GridControl的使用以及怎样添加列和绑定数据源
    C#中使用Path、Directory、Split、Substring实现对文件路径和文件名的常用操作实例
    ZedGraph的曲线的LineItem对象的Tag属性存储信息进而在鼠标悬浮时进行显示
  • 原文地址:https://www.cnblogs.com/pubgoso/p/10829011.html
Copyright © 2020-2023  润新知