【九校3D2T3】世界第一的猛漢王

【問題描述】

卡普地公司舉辦了「世界第一的猛漢王」全球大會,來自世界各地的猛漢爲了爭奪「猛漢王」的名號前來一決高下。現在舉行的是弓箭組選拔賽。卡普地公司爲比賽新建了一張PVP地圖——「猛漢競技場」。有許多使用弓的猛漢在這裏互相較量。他們中的一些裝填了「接擊瓶」,這使得他們在接近戰中會佔有一定優勢,但是在遠程戰中會相當劣勢。具體來說如下:

假設q裝填了「接擊瓶」而p沒有,則當他們的曼哈頓距離大於D時,p壓制q,反之q壓制p。如果pq都裝填了「接擊瓶」或者都沒有,則他們之間仍然會存在一個客觀上的單向壓制關係,但是在比賽剛開始時無法得知。

競技場上一共有n+m個猛漢,其中n個裝填了「接擊瓶」,另外m個沒有。每個猛漢降臨到競技場時有一個座標(x, y)。Mark Douglas作爲上一屆的猛漢王正在觀看這場比賽,他希望得知場上有多少個「猛漢三角」。「猛漢三角」是指三個人uvw滿足u壓制vv壓制ww壓制u,且三人中至少有一人裝填了「接擊瓶」且至少有一人沒有。由於場上尚存在一些不明瞭的壓制關係,所以Mark希望知道可能的「猛漢三角」數量的最小值和最大值。

【輸入格式】

輸入文件名爲mhw.in

輸入第一行爲三個正整數n m D

接下來n行每行兩個正整數x y,表示裝填了「接擊瓶」的猛漢的座標。

接下來m行每行兩個正整數x y,表示沒有裝填「接擊瓶」的猛漢的座標。

可能有多個猛漢站在同一個位置。

【輸出格式】

輸出文件名爲mhw.out

 輸出兩個數min max,表示答案的最小值和最大值。

【樣例輸入與輸出】

example_mhw1.in

example_mhw1.out

2 2 1

1 2

1 1

3 1

2 2

0 2

 

 

難度確實大!

首先我們將猛漢們分爲兩個陣營(記爲黑色與白色)。我們一個猛漢三角就是形如a->c->b(a,b同陣營),然後在確定a,b之間的壓制關係得到最小或者最大值。

我們以白色陣營爲例。我們設cover[v]爲v壓制的對方陣營的數量,cover[v,u]爲v,u共同壓制的對方陣營的數量。minans=\sum min\left \{ cover[v]-cover[v,u] \right cover[u]-cover[v,u]\},maxans同理。

minans=\sum min\left \{ cover[v] \right cover[u]\}-\sum cover[v,u]。對於cover[v,u],我們就算另一方陣營對\sum cover[v,u]的貢獻就行了。如果一個猛漢被對面的k個人壓制,那麼他對\sum cover[v,u]的貢獻就是\frac{k*(k-1)}{2}

求cover數組可以用掃描+線段樹。

代碼:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<ctime>
#include<queue>
#define ll long long
#define N 100005

using namespace std;
inline ll Get() {ll x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}while('0'<=ch&&ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}return x*f;}

ll n,m,lim;
ll mn,mx;
ll cc;
ll d[N*6];
ll cnt;
ll c[2][N];

struct line {
	ll x,op,col,id;
	ll l,r;
	bool operator <(const line &a)const {
		if(x!=a.x) return x<a.x;
		return op<a.op;
	}
}st[N*6];

struct tree {
	ll l,r;
	ll sum[2];
}tr[N*25];

void build(ll v,ll l,ll r) {
	tr[v].l=l,tr[v].r=r;
	if(l==r) return ;
	ll mid=l+r>>1;
	build(v<<1,l,mid),build(v<<1|1,mid+1,r);
}

void Modify(ll v,ll l,ll r,ll tag,ll f) {
	if(tr[v].l>r||tr[v].r<l) return ;
	if(l<=tr[v].l&&tr[v].r<=r) {
		tr[v].sum[tag]+=f;
		return ;
	}
	Modify(v<<1,l,r,tag,f),Modify(v<<1|1,l,r,tag,f);
}

ll query(ll v,ll pos,ll tag) {
	if(tr[v].l>pos||tr[v].r<pos) return 0;
	if(tr[v].l==tr[v].r) return tr[v].sum[tag];
	return query(v<<1,pos,tag)+query(v<<1|1,pos,tag)+tr[v].sum[tag];
}

void work() {
	for(ll i=1;i<=cnt;i++) {
		if(st[i].op==-1) {
			Modify(1,st[i].l,st[i].r,st[i].col,1);
		} else if(st[i].op==0) {
			c[st[i].col][st[i].id]=query(1,st[i].l,st[i].col^1);
		} else {
			Modify(1,st[i].l,st[i].r,st[i].col,-1);
		}
	}
}

int main() {
	n=Get(),m=Get(),lim=Get();
	ll a,b,x,y;
	for(ll i=1;i<=n;i++) {
		a=Get(),b=Get();
		x=a+b,y=a-b;
		st[++cnt]=(line) {x-lim,-1,0,i,y-lim,y+lim};
		st[++cnt]=(line) {x,0,0,i,y};
		st[++cnt]=(line) {x+lim,1,0,i,y-lim,y+lim};
		d[++d[0]]=y;
		d[++d[0]]=y+lim;
		d[++d[0]]=y-lim;
	}
	for(ll i=1;i<=m;i++) {
		a=Get(),b=Get();
		x=a+b,y=a-b;
		st[++cnt]=(line) {x-lim,-1,1,i,y-lim,y+lim};
		st[++cnt]=(line) {x,0,1,i,y};
		st[++cnt]=(line) {x+lim,1,1,i,y-lim,y+lim};
		d[++d[0]]=y;
		d[++d[0]]=y+lim;
		d[++d[0]]=y-lim;
	}
	sort(st+1,st+1+cnt);
	sort(d+1,d+1+d[0]);
	cc=unique(d+1,d+1+d[0])-d;
	for(ll i=1;i<=cnt;i++) {
		st[i].l=lower_bound(d+1,d+cc,st[i].l)-d;
		st[i].r=lower_bound(d+1,d+cc,st[i].r)-d;
	}
	build(1,1,cc);
	
	work();
	for(ll i=1;i<=m;i++) c[1][i]=n-c[1][i];
	sort(c[0]+1,c[0]+1+n);
	sort(c[1]+1,c[1]+1+m);
	
	for(ll i=1;i<=n;i++) {
		mn+=(n-i)*c[0][i];
		mx+=(i-1)*c[0][i];
		ll x=1ll*(m-c[0][i])*(m-c[0][i]-1)/2;
		mn-=x,mx-=x;
	}
	for(ll i=1;i<=m;i++) {
		mn+=1ll*(m-i)*c[1][i];
		mx+=1ll*(i-1)*c[1][i];
		ll x=1ll*(n-c[1][i])*(n-c[1][i]-1)/2;
		mn-=x,mx-=x;
	}
	cout<<mn<<" "<<mx;
	return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章