跑用例2到最后都是正确答案与错误答案交替,原本应该只踢2000个人的最后踢了3万个人,代码也审不出什么问题
import java.io.*;
import java.util.LinkedList;
import java.util.Queue;
class Snode{
int lazy;//懒标记
int size=1;//该点数量
int sum=1;//该点及其子树的数量
int val;//该点的值,排序用
Snode pre;//父节点
Snode right;//左孩子
Snode left;//右孩子
}
class Main{
private static Snode root=null;//根节点
private static Snode rr=new Snode();//根节点的父节点,属于哨兵
private static int min,runSize=0;
public static int nextInt(StreamTokenizer st) throws IOException {
st.nextToken();
return (int)st.nval;
}
public static String next(StreamTokenizer st) throws IOException {
st.nextToken();
return st.sval;
}
public static void main(String[] args) throws IOException {
//StreamTokenizer st = new StreamTokenizer(new BufferedReader(new InputStreamReader(new FileInputStream("C:\\Users\\home\\Downloads\\P1486_2.in"))));
StreamTokenizer st = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
int n=nextInt(st);
min=nextInt(st);
String x;
int k;
Queue<Integer> que = new LinkedList<>();
insect(1000000);
for (int i = 0; i < n; i++) {
x=next(st);
k=nextInt(st);
if (x.equals("I")) {//新建一个工资档案,初始工资为k。如果某员工的初始工资低于工资下界,他将立刻离开公司。
insect(k);
} else if (x.equals("A")) {//把每位员工的工资加上 kk 。
root.val+=k;
root.lazy+=k;
} else if (x.equals("S")) {//把每位员工的工资扣除 kk。
root.val-=k;
root.lazy-=k;
if(root.lazy<0)flush();
}else {//查询第 k 多的工资。
if(root.sum<k+1)que.add(-1);
else {
Snode byK = getByK(root.sum-k);
que.add(byK.val);
}
}
}
flush();
//FileOutputStream stream = new FileOutputStream("C:\\Users\\home\\Downloads\\test.out");
for (Integer integer : que) {
System.out.println(integer);
//stream.write((integer+"\n").getBytes());
}
//stream.write((runSize+"\n").getBytes());
System.out.println(runSize);
}
/**
* 把节点n往上旋转,并维护指针
* @param n
*/
public static void rotate(Snode n){
Snode tmp=n.pre;
if (tmp.left==n) {
tmp.left=n.right;
if(n.right!=null)n.right.pre=tmp;
if(tmp.pre.left==tmp){
tmp.pre.left=n;
n.pre=tmp.pre;
}else {
tmp.pre.right=n;
n.pre=tmp.pre;
}
n.right=tmp;
tmp.pre=n;
}else {
tmp.right=n.left;
if(n.left!=null)n.left.pre=tmp;
if(tmp.pre.left==tmp){
tmp.pre.left=n;
n.pre=tmp.pre;
}else {
tmp.pre.right=n;
n.pre=tmp.pre;
}
n.left=tmp;
tmp.pre=n;
}
pushup(tmp);
pushup(n);
}
/**
* 新建一个工资档案,如果某员工的初始工资低于工资下界,他将立刻离开公司
* @param v
*/
public static void insect(int v){
if(v<min)return;
if(root==null){
root=new Snode();
root.val=v;
root.pre=rr;
rr.left=root;
return;
}
Snode r=root;
while (true){
pushdown(r);
if (v==r.val) {
r.size++;
break;
} else if (v>r.val) {
if (r.right == null) {
r.right=new Snode();
r.right.val=v;
r.right.pre=r;
r=r.right;
break;
}else r=r.right;
}else {
if (r.left == null) {
r.left=new Snode();
r.left.val=v;
r.left.pre=r;
r=r.left;
break;
}else r=r.left;
}
}
splay(r,rr);
}
/**
* 把n旋转为r的儿子
* @param n
* @param r
*/
public static void splay(Snode n,Snode r) {
while (n.pre!=r){
if (n.pre.pre==r) {
rotate(n);
}else {
if((n.pre.left==n&&n.pre.pre.left==n.pre)||(n.pre.right==n&&n.pre.pre.right==n.pre)){
rotate(n.pre);
}else {
rotate(n);
}
rotate(n);
}
}
if (r==rr) root=n;
}
/**
* 更新节点n
* @param n
*/
public static void pushup(Snode n){
n.sum=n.size;
if (n.right != null) n.sum+=n.right.sum;
if (n.left != null) n.sum+=n.left.sum;
}
/**
* 节点n的懒标记下放
* @param n
*/
public static void pushdown(Snode n){
if(n.lazy!=0){
if (n.right != null) {
n.right.val+=n.lazy;
n.right.lazy+=n.lazy;
}
if (n.left != null) {
n.left.val+=n.lazy;
n.left.lazy+=n.lazy;
}
n.lazy=0;
}
}
/**
* 获取工资排名第k的Snode对象
* @return 工资排名第k的Snode对象
*/
public static Snode getByK(int k){
Snode r=root;
while (true){
pushdown(r);
int le=0;
if(r.left!=null)le+=r.left.sum;
if(k>le&&k<=le+r.size){
return r;
}else if(k<=le){
r=r.left;
}else {
if(r.left!=null)k-=r.left.sum;
k-=r.size;
if(r.right!=null)r = r.right;
else return null;
}
}
}
/**
* 刷新懒标记,把工资低于min的人清理掉
*/
public static void flush(){
if(root==null)return;
Snode r=root;
while (true){
pushdown(r);
if(r.val==min)break;
if(r.val>min){
if(r.left==null)break;
if(r.left.val<min)break;
r=r.left;
}else {
if(r.right==null)break;
r=r.right;
}
}
splay(r,rr);
if(r.left!=null){
runSize+=r.left.sum;
r.left=null;
pushup(r);
}
}
}