zoukankan      html  css  js  c++  java
  • 题解 CF1354D 【Multiset】

    考试拿到题,一看,这不是权值线段树吗?

    思路

    使用线段树每个节点维护该区间内元素出现次数。

    根据题目,对于加入、删除元素,我们可以单点修改((+1)(-1)),对于输出,我们可 随便 遍历找一个出现次数为 (1) 的元素即可。

    代码

    具体解释见注释

    #include<bits/stdc++.h>
    #define re read()
    using namespace std;
    const int MAXN=1e6+10;
    int n,q,A[MAXN];
    struct SEGTREE{
    	int sum;//sum 最大为10^6 无需long long(我第一次手残开了,然后爆了空间)
    }tr[MAXN<<2];
    int read(){//快读
    	#define gt getchar()
    	#define isdi(a) (a>='0'&&a<='9')
    	int x=0,sgn=1;char ch=gt;
    	for(;!isdi(ch);ch=gt)if(ch=='-')sgn=-1;
    	for(;isdi(ch);ch=gt)x=(x<<1)+(x<<3)+(ch^48);
    	return x*sgn;
    }
    void build(int k,int l,int r){ //建树
    	if(l==r){
    		tr[k].sum=A[l];
    		return;
    	}
    	int mid=(l+r)>>1;
    	build(k<<1,l,mid); build(k<<1|1,mid+1,r);
    	tr[k].sum=tr[k<<1].sum+tr[k<<1|1].sum;
    	return;
    }
    void add(int k,int l,int r,int num){//加入元素
    	if(l==r){
    		if(l==num)tr[k].sum++;
    		return;
    	}
    	int mid=(l+r)>>1;
    	if(num>mid)add(k<<1|1,mid+1,r,num);
    	else add(k<<1,l,mid,num);
    	tr[k].sum++;
    	return;
    }
    void del(int k,int l,int r,int num){
    //删除该区间内第num大的元素
    	if(l==r){
    		if(tr[k].sum)tr[k].sum--;
    		return;
    	}
    	if(num>tr[k].sum)return;
    	int mid=(l+r)>>1;
    	if(num>tr[k<<1].sum)del(k<<1|1,mid+1,r,num-tr[k<<1].sum);
    //如果num大于左子树元素出现的总次数,则去右子树删第(num-左子树元素出现总次数)大的数
    	else if(num<=tr[k<<1].sum)del(k<<1,l,mid,num);
    //否则去左子树删除第num大的数
    	else return;
    	tr[k].sum--;
    //该区间内的次数减一
    	return;
    }
    int find(int k,int l,int r){//递归查找
    	if(l==r){
    		if(tr[k].sum)return l;
    		return 0;
    	}
    	int mid=(l+r)>>1;
    	if(tr[k<<1].sum)return find(k<<1,l,mid);
    	else return find(k<<1|1,mid+1,r);
    	return 0;
    //根据题目,随便找一个就行了,找不到就输出0
    }
    int main (){
    	n=re;q=re;
    	for(int i=1;i<=n;i++){
    		int temp=re;
    		A[temp]++;
    	}
    	build(1,1,n);
    	for(int i=1;i<=q;i++){
    		int k=re;
    		if(k<0)del(1,1,n,-k);
    		else add(1,1,n,k);
    	}
    	printf("%d",find(1,1,n));
    	return 0;
    }
    
  • 相关阅读:
    python安装教程
    protobuf安装教程
    PlantUML安装教程
    题解-CF1140E Palindrome-less Arrays
    FST
    线段树
    题解-CF677D Vanya and Treasure
    最短路
    后缀自动机
    虚树
  • 原文地址:https://www.cnblogs.com/werner-yin/p/13059021.html
Copyright © 2011-2022 走看看