题意:
n n n个数, a i ∈ [ L i , R i ] ⊂ [ 1 , k ] , k < = 5 a_i\in[L_i,R_i]\subset[1,k],k<=5 ai∈[Li,Ri]⊂[1,k],k<=5,有 m m m个限制,满足 ∣ a x i − a y i ∣ < = z i |a_{x_i}-a_{y_i}|<=z_i ∣axi−ayi∣<=zi。设 G = ∑ i = 1 n ∑ j = 1 n [ ∣ a i − a j ∣ < = 1 ] G=\sum_{i=1}^n\sum_{j=1}^n [|a_i-a_j|<=1] G=∑i=1n∑j=1n[∣ai−aj∣<=1]让你对每组询问输出 1 0 6 G + ∑ i = 2 k − 1 v i ( ∑ j = 1 n [ a j = = i ] ) 10^6G+\sum_{i=2}^{k-1}v_i(\sum_{j=1}^n[a_j==i]) 106G+∑i=2k−1vi(∑j=1n[aj==i])的最大值。
思路:
这题必须要先掌握两个套路,一个是切糕[HNOI2013]切糕和最小乘积树。
我们直接认为k=5,因此k<5和k=5是一样的。
然后我们发现,除非必须要填1或者5的位置,都必须填2,3,4。只有值域为1或者5 ;或者和必须填1或5的数相等的数才需要填1或者5。因此我们可以预先求出来这些数,然后剩下的只用考虑填2的数和填4的数,就足以计算出式子。
我们设 ( x , y ) = ( s u m 2 , s u m 4 ) (x,y)=(sum_2,sum_4) (x,y)=(sum2,sum4),我们只用考虑这个式子的最终形式,为 − A x y + B x + C y + Z ( A > 0 ) -Axy+Bx+Cy+Z(A>0) −Axy+Bx+Cy+Z(A>0),配一下 − A ( x − a ) ( y − b ) + C -A(x-a)(y-b)+C −A(x−a)(y−b)+C,那么这个就是求矩形面积的最小值(我们认为面积为负数也是可以的)。这和最小乘积树是基本一样的。不过这个矩形平移后可能会到达每个象限。稍微思考你会发现无论矩形怎么平移,最优值一定在凸包上,直接无脑的把凸包整个找出来即可,只需要找到x最小和x最大,然后分治找即可。
下面介绍一种比较简单的方法,同时对上面分治的部分进行更加详细的解释。
所有点都坐落在 [ x m i n , x m a x ] ∗ [ y m i n , y m a x ] [x_{min},x_{max}]*[y_{min},y_{max}] [xmin,xmax]∗[ymin,ymax]之中,分析一下题目,很明显 ( x m i n , y m i n ) , ( x m i n , y m a x ) , ( x m a x , y m i n ) (x_{min},y_{min}),(x_{min},y_{max}),(x_{max},y_{min}) (xmin,ymin),(xmin,ymax),(xmax,ymin)都是一定可以取到的。
如果矩形和一,二,四象限有交点,那么只需要考虑这三个点;如果全部在第三象限,那么只用考虑上凸壳(当然你没有必要判断,你只需要把凸壳上的点求出来,然后全部求一次即可)。
考虑找上凸壳:
求出距离线段 A B AB AB最远的点。我们用差乘来求距离。令 A ( x 1 , y 1 ) , B ( x 2 , y 2 ) A(x_1,y_1),B(x_2,y_2) A(x1,y1),B(x2,y2),你要求的点是 C ( x , y ) C(x,y) C(x,y)。 A B → × A C → = ( x 2 − x 1 ) ( y − y 1 ) − ( x − x 1 ) ( y 2 − y 1 ) \overrightarrow{AB} \times\overrightarrow{AC}=(x_2-x_1)(y-y_1)-(x-x_1)(y_2-y_1) AB ×AC =(x2−x1)(y−y1)−(x−x1)(y2−y1),那么选择2的影响是 y 1 − y 2 y1-y2 y1−y2,选择4的影响是 x 2 − x 1 x2-x1 x2−x1,选择3的影响是 0 0 0,求最大值。为了方便用切糕模型求解,我们把三个统统取反,然后求最小值,如果有负数,那么就把全部加上一个值使三个数都是正数。
时间复杂度:
凸包的上界为 O ( n 2 3 ) O(n^{\frac{2}{3}}) O(n32),网络流时间复杂度 O ( n 2 l o g n + n m + q ) O(n^2logn+nm+q) O(n2logn+nm+q),可以通过此题(当然我也不知道是怎么证的,反正能过就可以)。
cpp
#include<bits/stdc++.h>
#define rep(i,x,y) for(int i=x;i<=y;i++)
#define dwn(i,x,y) for(int i=x;i>=y;i--)
#define ll long long
using namespace std;
template<typename T>inline void qr(T &x){
x=0;int f=0;char s=getchar();
while(!isdigit(s))f|=s=='-',s=getchar();
while(isdigit(s))x=x*10+s-48,s=getchar();
x=f?-x:x;
}
int cc=0,buf[31];
template<typename T>inline void qw(T x){
if(x<0)putchar('-'),x=-x;
do{buf[++cc]=int(x%10);x/=10;}while(x);
while(cc)putchar(buf[cc--]+'0');
}
const int N=1e3+10;
const ll inf=4e18,inff=4e17;
int n,m,Q,k;
struct node1{
int x,y;
}a[N];
struct node2{
int x,y,z;
}b[N*3];
bool one[N],five[N];
int s1,s234,s5;
vector<pair<int,int> >e[N];
int tot,hd[N<<2],cur[N<<2],ver[N<<5],nxt[N<<5];ll w[N<<5];
int h[N<<2],st,ed;
bool v[N<<2];
void add(int x,int y,ll z){
tot++;
ver[tot]=y;w[tot]=z;
nxt[tot]=hd[x];
hd[x]=tot;
}
void link(int x,int y,ll z){
add(x,y,z),add(y,x,0);
}
bool bt_h(){
memset(h,0,sizeof(h));h[st]=1;
queue<int>q;q.push(st);
while(q.size()){
int x=q.front();q.pop();
for(int i=hd[x];i;i=nxt[i]){
int y=ver[i];
if(w[i]&&!h[y]){
h[y]=h[x]+1;
q.push(y);
}
}
}
return h[ed]!=0;
}
ll dfs(int x,ll f){
if(x==ed)return f;
ll res=f,tt;
for(int &i=cur[x];i;i=nxt[i]){
int y=ver[i];
if(w[i]&&h[y]==h[x]+1){
tt=dfs(y,min(res,w[i]));
w[i]-=tt,w[i^1]+=tt;
res-=tt;if(!res)break;
}
}
if(res==f)h[x]=0;
return f-res;
}
ll dinic(){
ll flow=0;
while(bt_h()){
memcpy(cur,hd,sizeof(cur));
flow+=dfs(st,inf);
}
return flow;
}
ll val[7];int vid[N][7],eid[N<<2];
void calc(ll &ans,ll &sum2,ll &sum4){
tot=1;memset(hd,0,sizeof(hd));
st=6*n+1,ed=st+1;
rep(i,1,n)link(st,i,inff);
rep(i,5*n+1,5*n+n)link(i,ed,inff);
int num=0;
rep(j,1,6)rep(i,1,n)vid[i][j]=++num;
rep(i,1,n){
rep(j,1,5){
if(j<a[i].x||j>a[i].y){
link(vid[i][j],vid[i][j+1],inff);
}
else{
link(vid[i][j],vid[i][j+1],val[j]);
}
}
}
rep(i,1,m){
int x=b[i].x,y=b[i].y,z=b[i].z;
if(x==y)continue;
rep(j,z+2,5){
link(vid[x][j],vid[y][j-z],inff);
link(vid[y][j],vid[x][j-z],inff);
}
}
ans=dinic();
memset(v,0,sizeof(v));
queue<int>q;q.push(st);v[st]=1;
while(q.size()){
int x=q.front();q.pop();
for(int i=hd[x];i;i=nxt[i]){
int y=ver[i];
if(w[i]&&!v[y]){
v[y]=1;
q.push(y);
}
}
}
sum2=0,sum4=0;
rep(p1,1,n)rep(p2,1,5){
int x=vid[p1][p2];
if(!v[x])continue;
for(int i=hd[x];i;i=nxt[i]){
int y=ver[i];
if(y!=st&&y!=ed&&(y-1)%n+1==p1&&(y-1)/n+1==p2+1&&!v[y]){
if(p2==2)sum2++;
if(p2==4)sum4++;
}
}
}
}
struct point{
ll x,y;
point(ll xx=0,ll yy=0):x(xx),y(yy){}
}c[N];int cnt;
ll det(ll x1,ll y1,ll x2,ll y2){
return x1*y2-x2*y1;
}
void cdq(ll x1,ll y1,ll x2,ll y2){
memset(val,0,sizeof(val));
val[2]=y2-y1,val[4]=x1-x2;
ll t=max(-val[2],-val[4]);
if(t>0){
rep(i,1,5)val[i]+=t;
}
ll x,y;
calc(t,x,y);
if(det(x2-x1,y2-y1,x-x1,y-y1)<=0)return;
c[++cnt]=point(x,y);
cdq(x1,y1,x,y);
cdq(x,y,x2,y2);
}
ll Cnt[7];
ll query(){
ll G=0,ret=0;
rep(i,1,5){
G+=Cnt[i]*Cnt[i];
if(i>1)G+=Cnt[i]*Cnt[i-1];
if(i<5)G+=Cnt[i]*Cnt[i+1];
ret+=Cnt[i]*val[i];
}
return G*1000000+ret;
}
void solve(){
qr(k),qr(n),qr(m),qr(Q);
rep(i,1,n)qr(a[i].x),qr(a[i].y);
rep(i,1,m)qr(b[i].x),qr(b[i].y),qr(b[i].z);
rep(i,1,n)e[i].clear();
rep(i,1,m){
e[b[i].x].push_back(make_pair(b[i].y,b[i].z));
e[b[i].y].push_back(make_pair(b[i].x,b[i].z));
}
memset(one,0,sizeof(one));
memset(five,0,sizeof(five));
s1=s5=0;
queue<int>q;
rep(i,1,n)if(a[i].y==1){
q.push(i);
one[i]=1;s1++;
}
while(q.size()){
int x=q.front();q.pop();
for(auto &[y,z]:e[x]){
if(!z&&!one[y]){
one[y]=1;
s1++;
q.push(y);
}
}
}
rep(i,1,n)if(a[i].x==5){
q.push(i);
five[i]=1;s5++;
}
while(q.size()){
int x=q.front();q.pop();
for(auto &[y,z]:e[x]){
if(!z&&!five[y]){
five[y]=1;
s5++;
q.push(y);
}
}
}
s234=n-s1-s5;
rep(i,1,n){
if(!one[i])a[i].x=max(a[i].x,2);
if(!five[i])a[i].y=min(a[i].y,4);
}
ll res,sum2,sum4;
ll minx,maxx,miny,maxy;
memset(val,0,sizeof(val));
val[2]=1;
calc(res,sum2,sum4);
minx=sum2;
val[2]=0;
val[4]=1;
calc(res,sum2,sum4);
miny=sum4;
val[4]=0;
val[3]=val[4]=1;
calc(res,sum2,sum4);
maxx=sum2;
val[3]=val[4]=0;
val[2]=val[3]=1;
calc(res,sum2,sum4);
maxy=sum4;
val[2]=val[3]=0;
cnt=0;
c[++cnt]=point(minx,miny);
c[++cnt]=point(minx,maxy);
c[++cnt]=point(maxx,miny);
cdq(minx,maxy,maxx,miny);
// cout<<"c:\n";
// rep(i,1,cnt)cout<<c[i].x<<" "<<c[i].y<<endl;
// cout<<"---------\n";
while(Q--){
memset(val,0,sizeof(val));
rep(i,2,k-1)qr(val[i]);
memset(Cnt,0,sizeof(Cnt));
Cnt[1]=s1;Cnt[5]=s5;
ll ans=-1;
rep(i,1,cnt){
Cnt[2]=c[i].x;
Cnt[4]=c[i].y;
Cnt[3]=s234-Cnt[2]-Cnt[4];
ans=max(ans,query());
}
qw(ans);puts("");
}
}
int main(){
// freopen("qip8.in","r",stdin);
// freopen("qip8.out","w",stdout);
int tt;qr(tt);qr(tt);
while(tt--)solve();
return 0;
}