求助,遇到些比较奇妙的问题
查看原帖
求助,遇到些比较奇妙的问题
533856
NuclearBomb楼主2022/9/27 00:52

跑用例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);
        }
    }
}
2022/9/27 00:52
加载中...