#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);
~~~~~^~~~~~~~~~~~~~~~
# |
Verdict |
Execution time |
Memory |
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 |
# |
Verdict |
Execution time |
Memory |
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 |
# |
Verdict |
Execution time |
Memory |
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 |