답안 #210528

# 제출 시각 아이디 문제 언어 결과 실행 시간 메모리
210528 2020-03-17T15:33:16 Z arnold518 Dragon 2 (JOI17_dragon2) C++14
100 / 100
1612 ms 23384 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(memo.find({s, e})!=memo.end())
		{
			printf("%lld\n", memo[{s, e}]);
			continue;
		}
		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);
			}
		}
		memo[{s, e}]=ans;
		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 5500 KB Output is correct
3 Correct 74 ms 5496 KB Output is correct
4 Correct 181 ms 11640 KB Output is correct
5 Correct 129 ms 11640 KB Output is correct
6 Correct 11 ms 4856 KB Output is correct
7 Correct 11 ms 4984 KB Output is correct
8 Correct 12 ms 5752 KB Output is correct
9 Correct 11 ms 5752 KB Output is correct
10 Correct 11 ms 5752 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 97 ms 23000 KB Output is correct
2 Correct 235 ms 20600 KB Output is correct
3 Correct 77 ms 18296 KB Output is correct
4 Correct 50 ms 14712 KB Output is correct
5 Correct 45 ms 11256 KB Output is correct
6 Correct 74 ms 22936 KB Output is correct
7 Correct 75 ms 23064 KB Output is correct
8 Correct 67 ms 23052 KB Output is correct
9 Correct 55 ms 22940 KB Output is correct
10 Correct 52 ms 22936 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 14 ms 5752 KB Output is correct
2 Correct 23 ms 5500 KB Output is correct
3 Correct 74 ms 5496 KB Output is correct
4 Correct 181 ms 11640 KB Output is correct
5 Correct 129 ms 11640 KB Output is correct
6 Correct 11 ms 4856 KB Output is correct
7 Correct 11 ms 4984 KB Output is correct
8 Correct 12 ms 5752 KB Output is correct
9 Correct 11 ms 5752 KB Output is correct
10 Correct 11 ms 5752 KB Output is correct
11 Correct 97 ms 23000 KB Output is correct
12 Correct 235 ms 20600 KB Output is correct
13 Correct 77 ms 18296 KB Output is correct
14 Correct 50 ms 14712 KB Output is correct
15 Correct 45 ms 11256 KB Output is correct
16 Correct 74 ms 22936 KB Output is correct
17 Correct 75 ms 23064 KB Output is correct
18 Correct 67 ms 23052 KB Output is correct
19 Correct 55 ms 22940 KB Output is correct
20 Correct 52 ms 22936 KB Output is correct
21 Correct 98 ms 22940 KB Output is correct
22 Correct 244 ms 20696 KB Output is correct
23 Correct 1258 ms 18552 KB Output is correct
24 Correct 1612 ms 21368 KB Output is correct
25 Correct 241 ms 18424 KB Output is correct
26 Correct 177 ms 17656 KB Output is correct
27 Correct 49 ms 12024 KB Output is correct
28 Correct 50 ms 12024 KB Output is correct
29 Correct 262 ms 23384 KB Output is correct
30 Correct 168 ms 23108 KB Output is correct
31 Correct 169 ms 22996 KB Output is correct
32 Correct 213 ms 20100 KB Output is correct
33 Correct 950 ms 20088 KB Output is correct
34 Correct 171 ms 20004 KB Output is correct
35 Correct 164 ms 17528 KB Output is correct
36 Correct 178 ms 17528 KB Output is correct
37 Correct 185 ms 17528 KB Output is correct
38 Correct 955 ms 20600 KB Output is correct
39 Correct 1150 ms 20088 KB Output is correct
40 Correct 978 ms 20088 KB Output is correct
41 Correct 279 ms 22672 KB Output is correct
42 Correct 340 ms 22136 KB Output is correct
43 Correct 410 ms 21880 KB Output is correct
44 Correct 114 ms 17556 KB Output is correct
45 Correct 106 ms 17244 KB Output is correct
46 Correct 97 ms 17032 KB Output is correct
47 Correct 93 ms 17560 KB Output is correct
48 Correct 87 ms 17176 KB Output is correct
49 Correct 89 ms 17168 KB Output is correct