답안 #210526

# 제출 시각 아이디 문제 언어 결과 실행 시간 메모리
210526 2020-03-17T15:26:47 Z arnold518 Dragon 2 (JOI17_dragon2) C++14
100 / 100
1439 ms 22920 KB
#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;

const int MAXN = 3e4;

struct Point { ll x, y; };
Point operator + (const Point &p, const Point &q) { return {p.x+q.x, p.y+q.y}; }
Point operator - (const Point &p, const Point &q) { return {p.x-q.x, p.y-q.y}; }

ll ccw(Point p, Point q) { return p.x*q.y-p.y*q.x; }
ll ccw(Point p, Point q1, Point q2) { return ccw(q1-p, q2-p); }

int N, M, Q;
vector<Point> P[MAXN+10];
Point A, B;
map<pii, ll> memo;

struct Node
{
	int val;
	Node *lc, *rc;
	Node() : val(0), lc(NULL), rc(NULL) {}
};

void makeTree(Node *node, int tl, int tr)
{
	if(tl==tr) return;
	int mid=tl+tr>>1;
	node->lc=new Node();
	node->rc=new Node();
	makeTree(node->lc, tl, mid);
	makeTree(node->rc, mid+1, tr);
}

bool cmpA(const Point &p, const Point &q)
{
	if((A.x<p.x || (A.x==p.x && A.y>p.y)) && (A.x<q.x || (A.x==q.x && A.y>q.y))) return ccw(A, p, q)>0;
	if((A.x>p.x || (A.x==p.x && A.y<p.y)) && (A.x>q.x || (A.x==q.x && A.y<q.y))) return ccw(A, p, q)>0;
	if((A.x<p.x || (A.x==p.x && A.y>p.y)) && (A.x>q.x || (A.x==q.x && A.y<q.y))) return true;
	if((A.x>p.x || (A.x==p.x && A.y<p.y)) && (A.x<q.x || (A.x==q.x && A.y>q.y))) return false;
}

bool cmpB(const Point &p, const Point &q)
{
	if((B.x<p.x || (B.x==p.x && B.y>p.y)) && (B.x<q.x || (B.x==q.x && B.y>q.y))) return ccw(B, p, q)>0;
	if((B.x>p.x || (B.x==p.x && B.y<p.y)) && (B.x>q.x || (B.x==q.x && B.y<q.y))) return ccw(B, p, q)>0;
	if((B.x<p.x || (B.x==p.x && B.y>p.y)) && (B.x>q.x || (B.x==q.x && B.y<q.y))) return true;
	if((B.x>p.x || (B.x==p.x && B.y<p.y)) && (B.x<q.x || (B.x==q.x && B.y>q.y))) return false;
}

struct Data
{
	int S;
	vector<Point> VA, VB;
	vector<pii> V;
	vector<Node*> tree;

	Node *addTree(Node *node, int tl, int tr, int pos)
	{
		if(pos<tl || tr<pos) return node;
		Node *ret=new Node();
		if(tl==tr)
		{
			ret->val=node->val+1;
			return ret;
		}
		int mid=tl+tr>>1;
		ret->lc=addTree(node->lc, tl, mid, pos);
		ret->rc=addTree(node->rc, mid+1, tr, pos);
		ret->val=(ret->lc->val)+(ret->rc->val);
		return ret;
	}

	int query(Node *nodel, Node *noder, int tl, int tr, int l, int r)
	{
		if(tr<l || r<tl) return 0;
		if(l<=tl && tr<=r) return (noder->val)-(nodel->val);
		int mid=tl+tr>>1;
		return query(nodel->lc, noder->lc, tl, mid, l, r)+query(nodel->rc, noder->rc, mid+1, tr, l, r);
	}

	void init()
	{
		int i, j;
		S=VA.size();
		if(S==0) return;
		sort(VA.begin(), VA.end(), cmpA);
		sort(VB.begin(), VB.end(), cmpB);

		vector<pair<Point, int>> VAT, VBT;
		for(i=0; i<S; i++) VAT.push_back({VA[i], i});
		for(i=0; i<S; i++) VBT.push_back({VB[i], i});
		sort(VAT.begin(), VAT.end(), [&](const pair<Point, int> &p, const pair<Point, int> &q) { return pll(p.first.x, p.first.y)<pll(q.first.x, q.first.y); });
		sort(VBT.begin(), VBT.end(), [&](const pair<Point, int> &p, const pair<Point, int> &q) { return pll(p.first.x, p.first.y)<pll(q.first.x, q.first.y); });

		for(i=0; i<S; i++)
		{
			int x=VAT[i].second+1, y=VBT[i].second+1;
			V.push_back({x, y});
		}
		sort(V.begin(), V.end());

		tree.push_back(new Node());
		makeTree(tree[0], 1, S);
		for(i=0; i<S; i++)
		{
			tree.push_back(addTree(tree.back(), 1, S, V[i].second));
		}
	}

	int query(Point pxl, Point pxr, Point pyl, Point pyr)
	{
		int i, j;
		if(S==0) return 0;
		int xl=(lower_bound(VA.begin(), VA.end(), pxl, cmpA)-VA.begin())%S+1;
		int xr=(upper_bound(VA.begin(), VA.end(), pxr, cmpA)-VA.begin()-1+S)%S+1;
		int yl=(lower_bound(VB.begin(), VB.end(), pyl, cmpB)-VB.begin())%S+1;
		int yr=(upper_bound(VB.begin(), VB.end(), pyr, cmpB)-VB.begin()-1+S)%S+1;

		if(!(ccw(A, pxl, VA[xl-1])>=0 && ccw(A, VA[xl-1], pxr)>=0)) return 0;
		if(!(ccw(A, pxl, VA[xr-1])>=0 && ccw(A, VA[xr-1], pxr)>=0)) return 0;
		if(!(ccw(B, pyl, VB[yl-1])>=0 && ccw(B, VB[yl-1], pyr)>=0)) return 0;
		if(!(ccw(B, pyl, VB[yr-1])>=0 && ccw(B, VB[yr-1], pyr)>=0)) return 0;

		int ret=0;

		if(xl<=xr)
		{
			if(yl<=yr)
			{
				ret+=query(tree[xl-1], tree[xr], 1, S, yl, yr);
			}
			else
			{
				ret+=query(tree[xl-1], tree[xr], 1, S, yl, S);
				ret+=query(tree[xl-1], tree[xr], 1, S, 1, yr);
			}
		}
		else
		{
			if(yl<=yr)
			{
				ret+=query(tree[0], tree[xr], 1, S, yl, yr);
				ret+=query(tree[xl-1], tree[S], 1, S, yl, yr);
			}
			else
			{
				ret+=query(tree[0], tree[xr], 1, S, yl, S);
				ret+=query(tree[0], tree[xr], 1, S, 1, yr);
				ret+=query(tree[xl-1], tree[S], 1, S, yl, S);
				ret+=query(tree[xl-1], tree[S], 1, S, 1, yr);
			}
		}
		return ret;
	}
};
Data D[MAXN+10];

int main()
{
	int i, j;

	scanf("%d%d", &N, &M);
	for(i=1; i<=N; i++)
	{
		int x, y, w;
		scanf("%d%d%d", &x, &y, &w);
		P[w].push_back({x, y});
	}
	scanf("%lld%lld%lld%lld", &A.x, &A.y, &B.x, &B.y);

	for(i=1; i<=M; i++)
	{
		for(auto it : P[i])
		{
			D[i].VA.push_back(it);
			D[i].VB.push_back(it);
		}
		D[i].init();
	}

	scanf("%d", &Q);
	while(Q--)
	{
		int s, e;
		ll ans=0;
		scanf("%d%d", &s, &e);
		if(P[s].size()<=P[e].size())
		{
			for(auto it : P[s])
			{
				Point pxl, pxr, pyl, pyr;
				pxl=it, pxr={2*A.x-it.x, 2*A.y-it.y};
				pyl=it, pyr={2*B.x-it.x, 2*B.y-it.y};
				if(ccw(A, it, B)<0) swap(pxl, pxr);
				if(ccw(B, it, A)<0) swap(pyl, pyr);
				ans+=D[e].query(pxl, pxr, pyl, pyr);
			}
		}
		else
		{
			for(auto it : P[e])
			{
				Point pxl, pxr, pyl, pyr;
				pxl=B, pxr={2*A.x-it.x, 2*A.y-it.y};
				pyl={2*B.x-it.x, 2*B.y-it.y}, pyr=A;
				if(ccw(A, pxl, pxr)<0) swap(pxl, pxr);
				if(ccw(B, pyl, pyr)<0) swap(pyl, pyr);
				ans+=D[s].query(pxl, pxr, pyl, pyr);

				pxl=it, pxr={2*A.x-it.x, 2*A.y-it.y};
				pyl=it, pyr={2*B.x-it.x, 2*B.y-it.y};
				if(ccw(A, it, B)>0) swap(pxl, pxr);
				if(ccw(B, it, A)>0) swap(pyl, pyr);
				ans+=D[s].query(pxl, pxr, pyl, pyr);
			}
		}
		printf("%lld\n", ans);
	}
}

Compilation message

dragon2.cpp: In function 'void makeTree(Node*, int, int)':
dragon2.cpp:32:12: warning: suggest parentheses around '+' inside '>>' [-Wparentheses]
  int mid=tl+tr>>1;
          ~~^~~
dragon2.cpp: In member function 'Node* Data::addTree(Node*, int, int, int)':
dragon2.cpp:71:13: warning: suggest parentheses around '+' inside '>>' [-Wparentheses]
   int mid=tl+tr>>1;
           ~~^~~
dragon2.cpp: In member function 'int Data::query(Node*, Node*, int, int, int, int)':
dragon2.cpp:82:13: warning: suggest parentheses around '+' inside '>>' [-Wparentheses]
   int mid=tl+tr>>1;
           ~~^~~
dragon2.cpp: In member function 'void Data::init()':
dragon2.cpp:88:10: warning: unused variable 'j' [-Wunused-variable]
   int i, j;
          ^
dragon2.cpp: In member function 'int Data::query(Point, Point, Point, Point)':
dragon2.cpp:117:7: warning: unused variable 'i' [-Wunused-variable]
   int i, j;
       ^
dragon2.cpp:117:10: warning: unused variable 'j' [-Wunused-variable]
   int i, j;
          ^
dragon2.cpp: In function 'int main()':
dragon2.cpp:165:9: warning: unused variable 'j' [-Wunused-variable]
  int i, j;
         ^
dragon2.cpp: In function 'bool cmpA(const Point&, const Point&)':
dragon2.cpp:45:1: warning: control reaches end of non-void function [-Wreturn-type]
 }
 ^
dragon2.cpp: In function 'bool cmpB(const Point&, const Point&)':
dragon2.cpp:53:1: warning: control reaches end of non-void function [-Wreturn-type]
 }
 ^
dragon2.cpp: In function 'int main()':
dragon2.cpp:167:7: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
  scanf("%d%d", &N, &M);
  ~~~~~^~~~~~~~~~~~~~~~
dragon2.cpp:171:8: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
   scanf("%d%d%d", &x, &y, &w);
   ~~~~~^~~~~~~~~~~~~~~~~~~~~~
dragon2.cpp:174:7: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
  scanf("%lld%lld%lld%lld", &A.x, &A.y, &B.x, &B.y);
  ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
dragon2.cpp:186:7: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
  scanf("%d", &Q);
  ~~~~~^~~~~~~~~~
dragon2.cpp:191:8: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
   scanf("%d%d", &s, &e);
   ~~~~~^~~~~~~~~~~~~~~~
# 결과 실행 시간 메모리 Grader output
1 Correct 14 ms 5752 KB Output is correct
2 Correct 23 ms 5496 KB Output is correct
3 Correct 69 ms 5240 KB Output is correct
4 Correct 96 ms 5240 KB Output is correct
5 Correct 57 ms 5240 KB Output is correct
6 Correct 11 ms 4728 KB Output is correct
7 Correct 11 ms 4856 KB Output is correct
8 Correct 12 ms 5756 KB Output is correct
9 Correct 11 ms 5752 KB Output is correct
10 Correct 11 ms 5624 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 98 ms 22876 KB Output is correct
2 Correct 236 ms 20476 KB Output is correct
3 Correct 75 ms 18168 KB Output is correct
4 Correct 49 ms 14584 KB Output is correct
5 Correct 46 ms 11128 KB Output is correct
6 Correct 73 ms 22808 KB Output is correct
7 Correct 72 ms 22812 KB Output is correct
8 Correct 68 ms 22920 KB Output is correct
9 Correct 53 ms 22812 KB Output is correct
10 Correct 51 ms 22808 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 14 ms 5752 KB Output is correct
2 Correct 23 ms 5496 KB Output is correct
3 Correct 69 ms 5240 KB Output is correct
4 Correct 96 ms 5240 KB Output is correct
5 Correct 57 ms 5240 KB Output is correct
6 Correct 11 ms 4728 KB Output is correct
7 Correct 11 ms 4856 KB Output is correct
8 Correct 12 ms 5756 KB Output is correct
9 Correct 11 ms 5752 KB Output is correct
10 Correct 11 ms 5624 KB Output is correct
11 Correct 98 ms 22876 KB Output is correct
12 Correct 236 ms 20476 KB Output is correct
13 Correct 75 ms 18168 KB Output is correct
14 Correct 49 ms 14584 KB Output is correct
15 Correct 46 ms 11128 KB Output is correct
16 Correct 73 ms 22808 KB Output is correct
17 Correct 72 ms 22812 KB Output is correct
18 Correct 68 ms 22920 KB Output is correct
19 Correct 53 ms 22812 KB Output is correct
20 Correct 51 ms 22808 KB Output is correct
21 Correct 97 ms 22864 KB Output is correct
22 Correct 231 ms 20472 KB Output is correct
23 Correct 1279 ms 18168 KB Output is correct
24 Correct 1439 ms 15096 KB Output is correct
25 Correct 161 ms 12024 KB Output is correct
26 Correct 105 ms 11256 KB Output is correct
27 Correct 46 ms 10872 KB Output is correct
28 Correct 49 ms 10872 KB Output is correct
29 Correct 164 ms 17364 KB Output is correct
30 Correct 101 ms 18248 KB Output is correct
31 Correct 105 ms 18264 KB Output is correct
32 Correct 119 ms 15224 KB Output is correct
33 Correct 848 ms 15228 KB Output is correct
34 Correct 102 ms 15352 KB Output is correct
35 Correct 94 ms 12792 KB Output is correct
36 Correct 107 ms 12792 KB Output is correct
37 Correct 106 ms 12920 KB Output is correct
38 Correct 824 ms 15736 KB Output is correct
39 Correct 1004 ms 15192 KB Output is correct
40 Correct 876 ms 15320 KB Output is correct
41 Correct 186 ms 17808 KB Output is correct
42 Correct 235 ms 17272 KB Output is correct
43 Correct 295 ms 16872 KB Output is correct
44 Correct 100 ms 17180 KB Output is correct
45 Correct 97 ms 16788 KB Output is correct
46 Correct 90 ms 16776 KB Output is correct
47 Correct 87 ms 17308 KB Output is correct
48 Correct 82 ms 16792 KB Output is correct
49 Correct 89 ms 16784 KB Output is correct