Educational Codeforces Round 87 (Rated for Div. 2) D树状数组加二分删除的值

Sample Input

5 4
1 2 3 4 5
-5 -1 -3 -1

Sample Output

3


思路,首先发现a[i]的值的范围是在1~n之间,每次插入我们可以直接把cnt[a[i]]++
删除的时候,要把所有在后面的数往前挪一位,那么其实也相当于所有在后面的数的前面
的cnt的前缀和减去1,于是利用树状数组动态维护前缀和,利用前缀和来找到删除的元素
时间复杂度O(nlogn)


#include<bits/stdc++.h>
using namespace std;
#define rep(i,j,k) for(LL i=(j); i<(k); ++i)
#define pb push_back
#define PII pair<LL,LL>
#define PLL pair<long long, long long>
#define ini(a,j) memset(a,j,sizeof a)
#define rrep(i,j,k) for(LL i=j; i>=k; --i)
#define fi first
#define se second
#define LL long long
#define beg begin()
#define ed end()
#define all(x) x.begin(),x.end()
const LL N=1e6+10;
int bit[N];
int lowbit(int x){
	return x&-x;
}
void update(int index){
	while(index<N){
		bit[index]++;
		index +=lowbit(index);
	}
}
void del(int index){
	while(index<N){
		bit[index]--;
		index +=lowbit(index);
	}
}
int query(int index){ //查询前缀和
	int ans=0;
	while(index>0){
		ans += bit[index];
		index -= lowbit(index);
	}
	return ans;
}
int main(int argc, char const *argv[])
{
	// #define DEBUG
	#ifdef DEBUG
		freopen("1.dat","r",stdin);
		freopen("ans.dat","w",stdout);
	#endif
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int n,m;
	cin>>n>>m;
	int t;
	rep(i,0,n){
		cin>>t;
		update(t);
	}
	rep(i,0,m){
		cin>>t;
		if(t>0)	update(t);
		else{
			t=-t;
			int left=1,right=n;
			int ans=0,mid=n;
			while(left<=right){
				mid=(left+right)>>1;
				if(query(mid)>=t){
					ans=mid;
					right=mid-1;
				}
				else left=mid+1;
			}
			del(ans);
		}		
	}
	rep(i,1,n+1)
		if(query(i)>0){
			cout<<i<<endl;
			return 0;
		}
	cout<<0<<endl;
	return 0;
}

猜你喜欢

转载自www.cnblogs.com/Crossea/p/12907100.html
今日推荐