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;
}
一条有梦想的咸鱼