bzoj 1503 (权值线段树)
由于蒟蒻实在是ttttttai 菜了,于是开始了学习主席树,权值线段树作为主席树的前置知识,于是蒟蒻各种百度百度,谷歌谷歌,抄网上的代码,然后终于A了这个题目。也还算是有一点收获。
题目:芝麻开门
题意:中文题,不解释。
思路:首先 升工资和降工资 可以用一个偏移量 tmp 来表示,但会有一个问题,因为可以在升工资和降工资之前新增成员,假设一开始就是满员工,那么升工资 tmp 直接 += ,降工资就判断所有小于minn的,然后删除(也就是置0)就ok了。 而对于中间的新增成员,更新的结点就应该是 (新成员工资 - tmp) (因为最后输出的时候是 原工资+偏移量,所以对于新成员,最开始时要提前减去已经存在的偏移量),但是这样很可能存在一个问题,为负。 故一开始就需要设立一个base,来避免这个问题;
AC代码:
#include<bits/stdc++.h>
#define debug(x) cout << "[" << #x <<": " << (x) <<"]"<< endl
#define pii pair<int,int>
#define clr(a,b) memset((a),b,sizeof(a))
#define rep(i,a,b) for(int i = a;i < b;i ++)
#define pb push_back
#define MP make_pair
#define LL long long
#define ull unsigned LL
#define ls i << 1
#define rs (i << 1) + 1
#define INT(t) int t; scanf("%d",&t)
using namespace std;
inline int read()
{
int x = 0;
char c = getchar();
bool flag = 0;
while(!isdigit(c)){if(c == '-')flag = 1;c = getchar();}
while(isdigit(c)){x = (x << 3) + (x << 1) + (c ^ 48);c = getchar();}
return flag ? -x : x;
}
const int maxn = 4e5 + 20;
const int base = 2e5 + 1;
int sum[maxn * 4];
int lazy[maxn * 4];
void pushDown(int i){
if(lazy[i]){
sum[i << 1] = sum[i << 1 | 1] = 0;
lazy[i << 1] = lazy[i << 1 | 1] = 1;
lazy[i] = 0;
}
}
void isrt(int pos,int l,int r,int i){
if(l == r){
if(l == pos) ++ sum[i];
return ;
}
int mid = (l + r) >> 1;
pushDown(i);
if(pos <= mid) isrt(pos,l,mid,i << 1);
if(pos > mid) isrt(pos,mid + 1,r,i << 1 | 1);
sum[i] = sum[i << 1] + sum[i << 1 | 1];
}
void udt(int l,int r,int ul,int ur,int i){
pushDown(i);
if(ul <= l && r <= ur){
sum[i] = 0;
lazy[i] = 1;
return ;
}
int mid = (l + r) >> 1;
if(ul <= mid) udt(l,mid,ul,ur,i << 1);
if(ur > mid) udt(mid + 1,r,ul,ur,i << 1 | 1);
sum[i] = sum[i << 1] + sum[i << 1 | 1];
}
int Kth(int l,int r,int i,int k){
int mid = (l + r) >> 1;
pushDown(i);
if(l == r) return l;
if(sum[i << 1 | 1] >= k){
return Kth(mid + 1,r,i << 1 | 1,k);
}
else
return Kth(l,mid,i << 1,k - sum[i << 1 | 1]);
}
int main()
{
int n,minn; scanf("%d%d",&n,&minn);
int ans = 0,tmp = 0;
clr(sum,0); clr(lazy,0);
while(n --){
char ch; int k;
scanf(" %c%d",&ch,&k);
if(ch == 'I'){
if(k < minn) continue;
++ ans;
isrt(k - tmp + base,1,maxn - 1,1); /// k,k - tmp + base
//debug(sum[1]);
// debug(sum[3]);
}
else if(ch == 'A')
tmp += k;
else if(ch == 'S'){
tmp -= k;
udt(1,maxn - 1,1,minn - tmp + base - 1,1); /// x + tmp < minn,x < minn - tmp,区间是闭区间,所以 minn - tmp + base - 1
}
else {
//debug(sum[1]);
if(sum[1] < k) printf("-1\n");
else{
printf("%d\n",Kth(1,maxn - 1,1,k) - base + tmp);
}
}
}
printf("%d\n",ans - sum[1]);
return 0;
}
版权声明:本文为no_O_ac原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。