test20260713

\(P3459\)

每一次的修高速,会影响从根到这条边所连的字数的所有点
修完这一次高速,所有这些点,到根就少走一条土路
所以就是子树修改
查询就是深度-1,在减去子树修改里面所累加的少走的土路数

\(P3558\)

首先虽然可以通过操作改变每一个元素的值
但是发现无论怎么改变这个值,都还是\(0,1,-1\)
因为变化太大不仅没有意义,而且该会让后面的数不好操作
\(f_{i,-1/0/1}\)表示把第\(i\)个数变成\(0,1,-1\)后,让\(1\)\(i\)的元素满足非递减时的最小操作次数
初始化:
所有\(f\)初始为无穷大,然后\(f_{1,a_1}=0\)
转移很好转移,分别按照\(a_i\)和目标想要变成什么讨论,注意要判断无解

\(P9525\)

先把所有人都加入到三个优先队列中,每一次尝试用三个优先队列的最大值,如果合法
那就直接输出答案
不然就把阻碍别人的最大值给标记掉,不要了
为什么判断某个最大值在不是自己应该占有的维度上追平了别的最大值(y[X]>=y[Y])
可以直接把这个X给彻底不要了,因为这说明这个最大值在至少两个维度成为了全场最大,那么无论谁和组队,都会占掉至少两个优势位置,所以就必然会让队友没有特长
所以这个最大值可以直接标记,弹出

fore(i, 1, n) {
        int x = A.top().id;
        int y = B.top().id;
        int z = C.top().id;
        if(b[x] >= b[y] || c[x] >= c[z]) vis[x] = 1;
        if(a[y] >= a[x] || c[y] >= c[z]) vis[y] = 1;
        if(a[z] >= a[x] || b[z] >= b[y]) vis[z] = 1;
        if(!vis[x] && !vis[y] && !vis[z]) {
            cout << a[x] + b[y] + c[z] << '\n';
            return 0;
        }
        while(!A.empty() && vis[A.top().id] == 1) A.pop();
        while(!B.empty() && vis[B.top().id] == 1) B.pop();
        while(!C.empty() && vis[C.top().id] == 1) C.pop();
    }

\(P5749\)

首先对于一些尺码相同的鞋子,例如
\(-2,2,-2,2\)
肯定会让靠左边的\(-2,2\)配对,然后靠右边的配对
同样的,如果他们中间在隔了一些数也是会这样配对,因为如果交错配对,中间的一部分数,就会被反复交换,不好
所以先用一个\(vector\)把每个值的位置存下来,然后右往左扫,每一个位置和这个位置应该要配对的值的最右边位置配对 (把左边那个对应的位置,一路交换过来)
然后这个交换的次数,就是这一路上,还没有配对好的数(配对好的数在交换的时候,会把这个对应位置的数给挪一下)
这个用树桩数组维护

posted @ 2026-07-13 14:16  wmq2012  阅读(9)  评论(0)    收藏  举报