注意到在时刻$t\in [1,n]$第$i$次使用$2$类法术,对应伤害值即$t-i$
将两边分别求和,即伤害值仅取决于使用第$2$类法术的次数和时刻和
记对应信息分别为$C/S_{X/Y}$,最终总伤害值即$S_{X}+S_{Y}-\frac{C_{X}(C_{X}+1)}{2}-\frac{C_{Y}(C_{Y}+1)}{2}$
在此基础上,将$(a_{i},b_{i},c_{i},d_{i})$分为以下四类:
- $(a_{i},b_{i})=(c_{i},d_{i})$
- $\{(a_{i},b_{i}),(c_{i},d_{i})\}=\{(1,2),(2,1)\}$(注意是集合)
- $\{(a_{i},b_{i}),(c_{i},d_{i})\}=\{(1,1),(2,2)\}$
- $(a_{i},b_{i})$和$(c_{i},d_{i})$恰有一维相同
对于第1类,其影响已经确定,直接统计即可
对于第2类,已经确定$\Delta C_{X}+\Delta C_{Y}$和$\Delta S_{X}+\Delta S_{Y}$,枚举前者划分方式即可
对于第3类,枚举其中选$(1,1)$的次数$k$,则$\Delta S_{X}=\Delta S_{Y}=$最大的$k$个$i$之和
对于第4类,统计出影响已经确定的部分,剩余部分的选择仅取决于对应的$C_{X/Y}$
具体的,其总是不断将最大的$i$取$2$直至(该次)$\Delta ans<0$,进而简单预处理即可
时间复杂度为$o(n^{2})$,可以通过
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 8005 4 int n,a,b,c,d,cx,cy,c2,c3,s,ans,sum[N],fx[N],fy[N]; 5 vector<int>v3,vx4,vy4; 6 int main(){ 7 scanf("%d",&n); 8 for(int i=1;i<=n;i++){ 9 scanf("%d%d%d%d",&a,&b,&c,&d); 10 if ((a==c)&&(a==2))cx++,s+=i; 11 if ((b==d)&&(b==2))cy++,s+=i; 12 if ((a!=c)&&(b!=d)){ 13 if (a!=b)c2++,s+=i; 14 else v3.push_back(i); 15 } 16 if ((a==c)^(b==d)){ 17 if (a!=c)vx4.push_back(i); 18 else vy4.push_back(i); 19 } 20 } 21 reverse(v3.begin(),v3.end()); 22 reverse(vx4.begin(),vx4.end()); 23 reverse(vy4.begin(),vy4.end()); 24 for(int i=0;i<v3.size();i++)sum[i+1]=sum[i]+(v3[i]<<1); 25 for(int i=0;i<=n;i++){ 26 fx[i]=-i*(i+1)/2; 27 for(int j=0;j<vx4.size();j++)fx[i]+=max(vx4[j]-i-j-1,0); 28 } 29 for(int i=0;i<=n;i++){ 30 fy[i]=-i*(i+1)/2; 31 for(int j=0;j<vy4.size();j++)fy[i]+=max(vy4[j]-i-j-1,0); 32 } 33 for(int i=0;i<=c2;i++) 34 for(int j=0;j<=v3.size();j++){ 35 int CX=cx+i+j,CY=cy+(c2-i)+j; 36 ans=max(ans,s+sum[j]+fx[CX]+fy[CY]); 37 } 38 printf("%lld\n",ans); 39 return 0; 40 }