test20180922 世界第一的猛汉王

题意

分析


由于异色点必有连边,所以一个点的covered减去两个点共有的covered就是可存在的环数,十分巧妙。

#include <bits/stdc++.h>

using LL = long long;

const int MAXN = 1e5 + 5;

int n, m, D;

std::pair<LL, LL> p1[MAXN], p2[MAXN];

struct Event {
    LL x, y; int val;
    
    Event() = default;
    Event(LL _x, LL _y, int _v): x(_x), y(_y), val(_v) {}
}; std::vector<Event> events; // 扫描线事件 
std::vector<LL> xlist, sorted; // x离散化列表,y离散化列表 

namespace BIT {
    int sum[MAXN * 3];
    
    void Init() {
        memset(sum, 0, sizeof sum);
    }
    
#define lowbit(x) ((x) & -(x))
    
    void Add(int a, int x) {
        for (int i = a; i <= (int)sorted.size(); i += lowbit(i))
            sum[i] += x;
    }
    
    int Query(int a) {
        int res = 0;
        for (int i = a; i > 0; i -= lowbit(i))
            res += sum[i];
        return res;
    }
}

LL minAns = 0, maxAns = 0, minus = 0; // 加、减的总和 

int covered[MAXN];

int Y(LL y) {
    return std::lower_bound(sorted.begin(), sorted.end(), y) - sorted.begin() + 1;
}

LL C2(LL x) {
    return x * (x - 1) / 2;
}

void Solve() {
    events.clear(); // p2中x起止&y&+-1 
    xlist.clear(); // p2中x起止, p1中x 
    sorted.clear(); // p2中y,p1中y起止 
    
    for (int i = 1; i <= m; ++i) {
        events.emplace_back(p2[i].first - D, p2[i].second, 1);
        events.emplace_back(p2[i].first + D + 1, p2[i].second, -1);
        
        xlist.push_back(p2[i].first - D);
        xlist.push_back(p2[i].first + D + 1);
        
        sorted.push_back(p2[i].second);
    }
    for (int i = 1; i <= n; ++i) {
        xlist.push_back(p1[i].first);
        
        sorted.push_back(p1[i].second - D - 1);
        sorted.push_back(p1[i].second + D);
    }
    
    std::sort(xlist.begin(), xlist.end());
    xlist.erase(std::unique(xlist.begin(), xlist.end()), xlist.end());
    
    std::sort(sorted.begin(), sorted.end());
    sorted.erase(std::unique(sorted.begin(), sorted.end()), sorted.end());
    
    std::sort(events.begin(), events.end(), [] (const Event &a, const Event &b) { return a.x < b.x; });
    
    BIT::Init();
     
    int j1 = 0, j2 = 1;
    
    for (LL x: xlist) {
        while (j1 < (int)events.size() && events[j1].x == x) { // 把离散化的纵坐标加进去 
            BIT::Add(Y(events[j1].y), events[j1].val);
            ++j1;
        }
        
        while (j2 <= n && p1[j2].first == x) {
            covered[j2] = BIT::Query(Y(p1[j2].second + D)) - BIT::Query(Y(p1[j2].second - D - 1)); // 询问离散化的纵坐标的区间和 
            ++j2;
        }
    }
    
    std::sort(covered + 1, covered + n + 1);
    
    for (int i = 1; i <= n; ++i) {
        minAns += 1LL * (n - i) * covered[i]; // n-i个比它大 
        maxAns += 1LL * (n - i) * covered[n - i + 1]; // n-i个比它小 
        minus += C2(covered[i]); // 加到减的总和里面 
    }
}

int main() {
#ifndef LOCAL
    freopen("mhw.in", "r", stdin);
    freopen("mhw.out", "w", stdout);
#endif
    
    scanf("%d%d%d", &n, &m, &D);
    for (int i = 1; i <= n; ++i) {
        static int x, y;
        
        scanf("%d%d", &x, &y);
        p1[i] = std::make_pair(x + y, x - y);
    }
    for (int i = 1; i <= m; ++i) {
        static int x, y;
        
        scanf("%d%d", &x, &y);
        p2[i] = std::make_pair(x + y, x - y);
    }
    std::sort(p1 + 1, p1 + n + 1);
    std::sort(p2 + 1, p2 + m + 1);
    
    Solve();
    
    std::swap(n, m);
    std::swap(p1, p2);
    
    Solve();
    
    printf("%lld %lld\n", minAns - minus, maxAns - minus);
    
    return 0;
}

mine

#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<ctime>
#include<iostream>
#include<string>
#include<vector>
#include<list>
#include<deque>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<bitset>
#include<algorithm>
#include<complex>
#pragma GCC optimize ("O0")
using namespace std;
template<class T> inline T read(T&x)
{
    T data=0;
	int w=1;
    char ch=getchar();
    while(!isdigit(ch))
    {
		if(ch=='-')
			w=-1;
		ch=getchar();
	}
    while(isdigit(ch))
        data=10*data+ch-'0',ch=getchar();
    return x=data*w;
}
typedef long long ll;
const int INF=0x7fffffff;

const int MAXN=1e5+7;
int n,m,D;

pair<ll,ll> p1[MAXN],p2[MAXN];

struct Event
{
	ll x,y;
	int val;
	
	Event()=default;
	Event(ll x,ll y,int v): x(x),y(y),val(v) {}
};
vector<Event> events;
vector<ll> xlist,sorted;

struct BIT
{
	int sum[MAXN*3];
	
	void init()
	{
		memset(sum,0,sizeof(sum));
	}
#define lowbit(x) ((x)&(-x))
	void add(int p,int v)
	{
		for(int i=p;i<=(int)sorted.size();i+=lowbit(i))
			sum[i]+=v;
	}
	
	int query(int p)
	{
		int res=0;
		for(int i=p;i>0;i-=lowbit(i))
			res+=sum[i];
		return res;
	}
}T;

ll minans,maxans,minussum;
int covered[MAXN];

int Y(ll y)
{
	return lower_bound(sorted.begin(),sorted.end(),y)-sorted.begin()+1;
}

ll C2(ll x)
{
	return x*(x-1)/2;
}

void solve()
{
	events.clear();
	xlist.clear();
	sorted.clear();
	
	for(int i=1;i<=m;++i)
	{
		events.emplace_back(p2[i].first-D,p2[i].second,1);
		events.emplace_back(p2[i].first+D+1,p2[i].second,-1);
		
		xlist.push_back(p2[i].first-D);
		xlist.push_back(p2[i].first+D+1);
		
		sorted.push_back(p2[i].second);
	}
	
	for(int i=1;i<=n;++i)
	{
		xlist.push_back(p1[i].first);
		
		sorted.push_back(p1[i].second-D-1); // 查询的时候用 
		sorted.push_back(p1[i].second+D);
	}
	
	sort(xlist.begin(),xlist.end());
	xlist.erase(unique(xlist.begin(),xlist.end()),xlist.end());
	
	sort(sorted.begin(),sorted.end());
	sorted.erase(unique(sorted.begin(),sorted.end()),sorted.end());
	
	sort(events.begin(),events.end(),[] (const Event &a,const Event &b) { return a.x<b.x; });
	
	T.init();
	
	int i=0,j=1;
	
	for(ll x:xlist)
	{
		while(i<(int)events.size()&&events[i].x==x)
		{
			T.add(Y(events[i].y),events[i].val);
			++i;
		}
		while(j<=n&&p1[j].first==x)
		{
			covered[j]=T.query(Y(p1[j].second+D))-T.query(Y(p1[j].second-D-1));
			++j;
		}
	}
	
	sort(covered+1,covered+n+1);
	
	for(int i=1;i<=n;++i)
	{
		minans+=(ll)(n-i)*covered[i];
		maxans+=(ll)(i-1)*covered[i];
		minussum+=C2(covered[i]);
	}
}

int main()
{
  freopen("mhw.in","r",stdin);
  freopen("mhw.out","w",stdout);
	read(n);read(m);read(D);
	for(int i=1;i<=n;++i)
	{
		static int x,y;
		read(x);read(y);
		p1[i]=make_pair(x+y,x-y);
	}
	for(int i=1;i<=m;++i)
	{
		static int x,y;
		read(x);read(y);
		p2[i]=make_pair(x+y,x-y);
	}
	sort(p1+1,p1+n+1);
	sort(p2+1,p2+m+1);
	
	solve();
	
	swap(n,m);
	swap(p1,p2);
	solve();
	
	printf("%lld %lld\n",minans-minussum,maxans-minussum);
//  fclose(stdin);
//  fclose(stdout);
    return 0;
}

posted on 2018-09-26 22:31  autoint  阅读(413)  评论(0编辑  收藏  举报

导航