题解 鱼死网破
首先发现纵坐标都相同的时候可以从上面每个点向下面一条线算投影
还可以发现纵坐标都相同而且强制在线的话可以人类智慧
然后正解:
感觉可以对每个端点分开考虑比较不好想
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 2000010
#define fir first
#define sec second
#define pb push_back
#define ll long long
// #define int long long
char buf[1<<21], *p1=buf, *p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
inline int read() {
int ans=0, f=1; char c=getchar();
while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
return ans*f;
}
int n, k, m, op;
pair<ll, ll> p[N], q[N];
int a[N], b[N], c[N];
inline ll gcd(ll a, ll b) {return !b?a:gcd(b, a%b);}
inline pair<ll, ll> slope(ll x, ll y) {ll t=gcd(x, y); if (!t) return {-1,-1}; return {x/t, y/t};}
bool sameline(pair<ll, ll> a, pair<ll, ll> b, pair<ll, ll> c) {
return slope(a.fir-b.fir, a.sec-b.sec)==slope(b.fir-c.fir, b.sec-c.sec);
}
namespace force{
void solve() {
for (int i=1,ans=0,x,y; i<=m; ++i) {
// cout<<"i: "<<i<<endl;
x=read()^(ans*op); y=read()^(ans*op); ans=0;
for (int j=1; j<=n; ++j) {
// cout<<"j: "<<j<<endl;
if (x==p[j].fir) {
for (int t=1; t<=::k; ++t)
if (c[t]<p[j].sec && a[t]<=x && b[t]>=x) goto jump;
}
else {
double k=(1.0*p[j].sec-y)/(1.0*p[j].fir-x), b=y-k*x;
for (int t=1; t<=::k; ++t) {
double pos=(c[t]-b)/k;
// cout<<"t: "<<t<<' '<<pos<<endl;
if (c[t]<p[j].sec && a[t]<=pos && ::b[t]>=pos) goto jump;
if (c[t]<p[j].sec && (sameline({x, y}, {a[t], c[t]}, p[j])||sameline({x, y}, {::b[t], c[t]}, p[j]))) goto jump;
}
}
// cout<<"add: "<<p[j].fir<<' '<<p[j].sec<<endl;
++ans;
jump: ;
}
printf("%d\n", ans);
}
}
}
namespace task1{
pair<ll, ll> sta[N];
int tl[N<<2], tr[N<<2], val[N<<2], tag[N<<2], top;
#define tl(p) tl[p]
#define tr(p) tr[p]
#define val(p) val[p]
#define tag(p) tag[p]
#define pushup(p) val(p)=val(p<<1)+val(p<<1|1)
void spread(int p) {
if (!tag(p)) return ;
val(p<<1)+=tag(p); tag(p<<1)+=tag(p);
val(p<<1|1)+=tag(p); tag(p<<1|1)+=tag(p);
tag(p)=0;
}
void build(int p, int l, int r) {
tl(p)=l; tr(p)=r;
if (l==r) return ;
int mid=(l+r)>>1;
build(p<<1, l, mid);
build(p<<1|1, mid+1, r);
}
void upd(int p, int l, int r, int dat) {
if (l<=tl(p)&&r>=tr(p)) {val(p)+=dat; tag(p)+=dat; return ;}
spread(p);
int mid=(tl(p)+tr(p))>>1;
if (l<=mid) upd(p<<1, l, r, dat);
if (r>mid) upd(p<<1|1, l, r, dat);
pushup(p);
}
int query(int p, int pos) {
if (tl(p)==tr(p)) return val(p);
spread(p);
int mid=(tl(p)+tr(p))>>1;
if (pos<=mid) return query(p<<1, pos);
else return query(p<<1|1, pos);
}
void solve() {
build(1, -1000000, 1000000);
int x=read(), y=read(), ans=0;
for (int i=1; i<=n; ++i) {
// cout<<"i: "<<i<<' '<<p[i].fir<<' '<<p[i].sec<<endl;
top=0;
for (int j=1; j<=k; ++j) if (c[j]<p[i].sec) {
// cout<<"j: "<<j<<endl;
double K, B;
ll l, r;
if (a[j]!=p[i].fir) {
K=(1.0*p[i].sec-c[j])/(1.0*p[i].fir-a[j]), B=c[j]-K*a[j];
l=ceil((y-B)/K);
if (slope(p[i].fir-a[j], p[i].sec-c[j])==slope(a[j]-(l-1), c[j]-y)) --l;
// cout<<(y-B)/K<<endl;
}
else l=a[j];
if (b[j]!=p[i].fir) {
K=(1.0*p[i].sec-c[j])/(1.0*p[i].fir-b[j]), B=c[j]-K*b[j];
r=floor((y-B)/K);
if (slope(p[i].fir-b[j], p[i].sec-c[j])==slope(b[j]-(r+1), c[j]-y)) ++r;
// cout<<(y-B)/K<<endl;
}
else r=b[j];
// cout<<"lr: "<<l<<' '<<r<<endl;
if (r<-1000000) continue;
if (l>1000000) continue;
if (l<=r) sta[++top]={l, r};
}
// cout<<"sta: "; for (int j=1; j<=top; ++j) cout<<"("<<sta[j].fir<<','<<sta[j].sec<<") "; cout<<endl;
if (!top) continue;
sort(sta+1, sta+top+1);
// cout<<"sta: "; for (int j=1; j<=top; ++j) cout<<"("<<sta[j].fir<<','<<sta[j].sec<<") "; cout<<endl;
ll lstl=sta[1].fir, lstr=sta[1].sec;
for (int j=2; j<=top; ++j) {
// cout<<"j: "<<j<<endl;
if (sta[j].fir<=lstr) lstr=max(lstr, sta[j].sec);
else {
// assert(lstl<=lstr);
upd(1, max(lstl, -1000000ll), min(lstr, 1000000ll), 1);
lstl=sta[j].fir, lstr=sta[j].sec;
}
}
// cout<<32<<endl;
// assert(lstl<=lstr);
upd(1, max(lstl, -1000000ll), min(lstr, 1000000ll), 1);
// cout<<1<<endl;
}
printf("%d\n", ans=(n-query(1, x)));
for (int i=2; i<=m; ++i) {
x=read()^(ans*op); y=read()^(ans*op);
printf("%d\n", ans=(n-query(1, x)));
}
}
}
namespace task{
struct vec{
ll a, b;
vec():a(0),b(0){}
vec(ll x, ll y):a(x),b(y){}
void put() {cout<<"("<<a<<','<<b<<") ";}
};
inline ll operator ^ (vec x, vec y) {return x.a*y.b-x.b*y.a;}
inline bool operator < (vec x, vec y) {return (x^y)>0;}
inline bool operator <= (vec x, vec y) {return (x^y)>=0;}
int top;
pair<ll, ll> pos[105];
struct tpl{vec fir, sec; int id;} sta[N];
vector<pair<vec, int>> line[105];
vector<vec> ln[105];
vector<int> pre[105];
inline bool operator < (tpl a, tpl b) {
if (a.fir<b.fir) return 1;
if (b.fir<a.fir) return 0;
if (b.sec<a.sec) return 1;
return 0;
}
void solve() {
for (int i=1; i<=k; ++i) pos[i<<1]={a[i], c[i]}, pos[i<<1|1]={b[i], c[i]};
for (int i=1; i<=n; ++i) {
top=0;
for (int j=1; j<=k; ++j) if (c[j]<p[i].sec)
sta[++top]={vec(a[j]-p[i].fir, c[j]-p[i].sec), vec(b[j]-p[i].fir, c[j]-p[i].sec), j};
sort(sta+1, sta+top+1);
// cout<<"fir: "; for (int j=1; j<=top; ++j) sta[j].fir.put(); cout<<endl;
// cout<<"sec: "; for (int j=1; j<=top; ++j) sta[j].sec.put(); cout<<endl;
if (!top) continue;
// vec rmax=sta[1].sec; int lst=1;
// for (int j=2; j<=top; ++j) {
// if (sta[j].sec<=rmax) ;
// else {
// line[sta[lst].id<<1].pb({sta[lst].fir, 1}), line[sta[lst].id<<1|1].pb({sta[lst].sec, -1});
// rmax=sta[j].sec; lst=j;
// }
// }
// line[sta[lst].id<<1].pb({sta[lst].fir, 1}), line[sta[lst].id<<1|1].pb({sta[lst].sec, -1});
vec lstl=sta[1].fir, lstr=sta[1].sec;
int lid=sta[1].id, rid=sta[1].id;
for (int j=2; j<=top; ++j) {
if (sta[j].fir<=lstr) {
if (lstr<sta[j].sec) lstr=sta[j].sec, rid=sta[j].id;
}
else {
line[lid<<1].pb({lstl, 1}), line[rid<<1|1].pb({lstr, -1});
lstl=sta[j].fir, lstr=sta[j].sec; lid=rid=sta[j].id;
}
}
line[lid<<1].pb({lstl, 1}), line[rid<<1|1].pb({lstr, -1});
}
for (int i=1,sum; i<=k; ++i) {
// cout<<"node: "<<i<<endl;
sort(line[i<<1].begin(), line[i<<1].end());
sort(line[i<<1|1].begin(), line[i<<1|1].end());
for (auto it:line[i<<1]) ln[i<<1].pb(it.fir), pre[i<<1].pb(it.sec); //, it.fir.put(); cout<<endl;
for (auto it:line[i<<1|1]) ln[i<<1|1].pb(it.fir), pre[i<<1|1].pb(it.sec); //, it.fir.put(); cout<<endl;
sum=0; for (auto& it:pre[i<<1]) sum=(it+=sum); //, cout<<sum<<' '; cout<<endl;
sum=0; for (auto& it:pre[i<<1|1]) sum=(it+=sum); //, cout<<sum<<' '; cout<<endl;
}
for (int i=1,x,y,ans=0; i<=m; ++i) {
x=read()^(ans*op), y=read()^(ans*op); ans=0;
for (int j=1; j<=k; ++j) {
// cout<<"j: "<<j<<endl;
vec v;
vector<vec>::iterator t;
v=vec(x-pos[j<<1].fir, y-pos[j<<1].sec);
// cout<<"v1: "; v.put(); cout<<endl;
t=upper_bound(ln[j<<1].begin(), ln[j<<1].end(), v);
if (t!=ln[j<<1].begin()) ans+=pre[j<<1][t-ln[j<<1].begin()-1]; //, cout<<"add1"<<endl;
v=vec(x-pos[j<<1|1].fir, y-pos[j<<1|1].sec);
// cout<<"v2: "; v.put(); cout<<endl;
t=lower_bound(ln[j<<1|1].begin(), ln[j<<1|1].end(), v);
if (t!=ln[j<<1|1].begin()) ans+=pre[j<<1|1][t-ln[j<<1|1].begin()-1]; //, cout<<"add2"<<endl;
}
printf("%d\n", ans=(n-ans));
}
}
}
signed main()
{
freopen("clash.in", "r", stdin);
freopen("clash.out", "w", stdout);
n=read(); k=read(); m=read(); op=read();
for (int i=1; i<=n; ++i) p[i].fir=read(), p[i].sec=read();
for (int i=1; i<=k; ++i) a[i]=read(), b[i]=read(), c[i]=read();
// if (n<=2000) force::solve();
// else task1::solve();
task::solve();
return 0;
}