题意:给出n个战士和他们各自的n批马,我们可以把马换给别的战士,但是都得换(即战士不能拥有原来的马),我们要每个战士乘以给他换的那个马的和最大。q次询问,每次把2个战士的马交换,输出和最大的答案。
做法:把战士根据值排序,我们可以证明每个战士一定不会给他分配排名与他相差超过2的马(可以枚举证明)。首先根据贪心我们可以发觉大的战士分配大的马一定是最好的,但是可能那个战士的排名与马的排名一样导致不能分配,所以如果出现这种情况我们就需要换。而互相换的范围不会超过3,我们可以想象这段排序后的区间是由每段不超过3的区间合并得到的最优值。其实可以直接dp即可,但是复杂度过高,我们可以利用线段树。每个节点维护一个a[i][j]代表左边有i个未被分配,右边有j个未被分配的最大和。合并时讨论中间有多少需要分配即可。
有个需要注意的地方:我们用x1,y1代表左子树,x2,y2代表右子树,如果y1=1,x2 = 0,按理应该是不需要讨论的,因为y1如果要分配只能跟自己分配,而x1,0的值肯定是大于等于(x1,1+最右边自己分配自己(如果可以))。所以当y1 != x2 && y1和x2有个为0就不需要讨论下去了。但是这个其实是不对的,比如,当右子树大小为1时,(x1,1)和(0,1)是可以合并成(x1,2)的。所以当x2 == 0 && x2+y2 == size && y1+y2 < 3的时候是可以合并的,左边也一样。
AC代码:
#pragma comment(linker, "/STACK:102400000,102400000")
#include<cstdio>
#include<ctype.h>
#include<algorithm>
#include<iostream>
#includ