当前位置:网站首页>【NOI模拟赛】计算几何(凸包,暴力,并查集)
【NOI模拟赛】计算几何(凸包,暴力,并查集)
2022-07-29 07:59:00 【DD(XYX)】
题面
一句话题意:给定平面上 n n n 个整点,求构成的凸包面积大小乘 2 的值。
数据生成方式:
给定 x 0 , y 0 , a x , a y , b x , b y , p x , p y , n x_0,y_0,a_x,a_y,b_x,b_y,p_x,p_y,n x0,y0,ax,ay,bx,by,px,py,n ,
x i = ( a x x i − 1 + b x ) m o d p x y i = ( a y y i − 1 + b y ) m o d p y x_i=(a_xx_{i-1}+b_x)\mod p_x\\ y_i=(a_yy_{i-1}+b_y)\mod p_y xi=(axxi−1+bx)modpxyi=(ayyi−1+by)modpy
最后得到 n n n 个点 ( x 0 , y 0 ) , ( x 1 , y 1 ) , . . . , ( x n − 1 , y n − 1 ) (x_0,y_0),(x_1,y_1),...,(x_{n-1},y_{n-1}) (x0,y0),(x1,y1),...,(xn−1,yn−1) 。
n ≤ 1018
px,py ≤ 200000
题解
我们发现这个 n 特别大,但是坐标值域比较小。
相信每个做过平面凸包的人都有过这样一个梦想:将横坐标每一个值对应的最小纵坐标和最大纵坐标求出来,当成两个序列做斜率优化求凸包。但是无奈值域通常是非常大的,这个想法一般用不了。
这道题就不一样了,至于比较小,我们完全可以求每一个横坐标对应的最小纵坐标和最大纵坐标。
根据鸽笼原理,n 特别大的时候横坐标和纵坐标一定会形成循环。
我们求出每一个纵坐标第一次出现的时刻(可以这么说吧)和第二次出现的时刻(如果有的话),然后从小到大/从大到小枚举纵坐标给横坐标赋值。由于不难发现只会形成一个循环,所以每个位置的第二时刻和第一时刻的差都是相等的。
我们对于每个纵坐标枚举对应的横坐标,暴力赋值,这其中需要跳过已经赋值过的横坐标。由于不管纵坐标是什么,相同纵坐标的下一个横坐标是仅取决于当前横坐标的,所以我们可以用并查集维护已经赋值过的连续段,确保可以 O ( log p ) O(\log p) O(logp) 跳过。
时间复杂度 O ( p log p ) O(p\log p) O(plogp) 。
CODE
// ubsan: undefined
// accoders
#include<map>
#include<set>
#include<cmath>
#include<ctime>
#include<queue>
#include<stack>
#include<random>
#include<bitset>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<unordered_map>
#pragma GCC optimize(2)
using namespace std;
#define MAXN 200005
#define LL long long
#define ULL unsigned long long
#define ENDL putchar('\n')
#define DB double
#define lowbit(x) (-(x) & (x))
#define FI first
#define SE second
#define PR pair<int,int>
#define UIN unsigned int
#define SQ 317
int xchar() {
static const int maxn = 1000000;
static char b[maxn];
static int pos = 0,len = 0;
if(pos == len) pos = 0,len = fread(b,1,maxn,stdin);
if(pos == len) return -1;
return b[pos ++];
}
// #define getchar() xchar()
inline LL read() {
LL f = 1,x = 0;int s = getchar();
while(s < '0' || s > '9') {
if(s<0)return -1;if(s=='-')f=-f;s = getchar();}
while(s >= '0' && s <= '9') {
x = (x<<1) + (x<<3) + (s^48);s = getchar();}
return f*x;
}
void putpos(LL x) {
if(!x)return ;putpos(x/10);putchar((x%10)^48);}
inline void putnum(LL x) {
if(!x) {
putchar('0');return ;}
if(x<0) putchar('-'),x = -x;
return putpos(x);
}
inline void AIput(LL x,int c) {
putnum(x);putchar(c);}
int n,m,s,o,k;
int l[MAXN],r[MAXN];
int P = 1;
struct it{
int a,b;LL c;
it(){
a=1;b=0;c=0;}
it(int A,int B,LL C){
a=A;b=B;c=C;}
}kx[MAXN],ky[MAXN];
inline it operator * (it l,it r) {
l.a = l.a*1ll*r.a % P;
l.b = (l.b*1ll*r.a + r.b) % P;
l.c += r.c; return l;
}
inline int operator * (int x,it y) {
return (x*1ll*y.a + y.b) % P;
}
PR fr[MAXN];
it la[MAXN];
int fa[MAXN];
it fe[MAXN];
int findf(int x) {
if(x == fa[x]) return x;
int r = fa[x],f = findf(r);
fe[x] = fe[x]*fe[r]; fa[x] = f;
return f;
}
void unionSet(int u,int f,it k) {
fa[u] = findf(f); fe[u] = k*fe[f];
}
PR ar[MAXN<<1];
int ca;
int st[MAXN],tp;
LL S(PR a,PR b,PR c) {
PR A = {
a.FI-b.FI,a.SE-b.SE};
PR B = {
c.FI-b.FI,c.SE-b.SE};
LL rs = A.SE*1ll*B.FI - A.FI*1ll*B.SE;
return rs<0 ? -rs:rs;
}
int main() {
freopen("geometry.in","r",stdin);
freopen("geometry.out","w",stdout);
int x0 = read(),y0 = read();
int ax = read(),ay = read();
int bx = read(),by = read();
it tx = it(ax,bx,1),ty = it(ay,by,1);
n = read();m = read();
LL N = read();
P = n;
for(int i = 1;i < n;i ++) kx[i] = kx[i-1]*tx;
P = m;
for(int i = 1;i < m;i ++) ky[i] = ky[i-1]*ty;
for(int i = 0;i < n;i ++) {
l[i] = m+1; r[i] = -1;
fa[i] = i; fe[i] = it();
}
P = m;
int p = y0,ct = 0,xx = x0;
while(!la[p].c && ct < N) {
if(!fr[p].FI) {
fr[p] = {
ct+1,xx};
}
else if(!la[p].c) {
la[p] = kx[ct-fr[p].FI+1];
}
p = p*ty; ct ++;
P = n; xx = xx*tx; P = m;
}
P = n;
for(int i = 0;i < m;i ++) {
if(fr[i].FI) {
int p = fr[i].SE;
LL cn = fr[i].FI-1;
findf(p); cn += fe[p].c;
p = fa[p];
while(cn < N) {
l[p] = min(l[p],i);
r[p] = max(r[p],i);
if(!la[i].c) break;
int nx = p*la[i];
if(findf(nx) == p) break;
unionSet(p,nx,la[i]);
findf(p); cn += fe[p].c;
p = fa[p];
}
}
}
for(int i = 0;i < n;i ++) fa[i] = i,fe[i] = it();
for(int i = m-1;i >= 0;i --) {
if(fr[i].FI) {
int p = fr[i].SE;
LL cn = fr[i].FI;
findf(p); cn += fe[p].c;
p = fa[p];
while(cn <= N) {
l[p] = min(l[p],i);
r[p] = max(r[p],i);
if(!la[i].c) break;
int nx = p*la[i];
if(findf(nx) == p) break;
unionSet(p,nx,la[i]);
findf(p); cn += fe[p].c;
p = fa[p];
}
}
}
int ll = n-1,rr = 0;
for(int i = 0;i < n;i ++) {
if(l[i] < n && r[i] >= 0) {
ll = min(ll,i); rr = max(rr,i);
}
}
tp = 0;
for(int i = ll;i <= rr;i ++) {
if(l[i] >= n || r[i] < 0) continue;
while(tp > 1 && (l[st[tp]]-l[st[tp-1]])*1ll*(i-st[tp]) >= (l[i]-l[st[tp]])*1ll*(st[tp]-st[tp-1])) {
st[tp --] = 0;
}
st[++ tp] = i;
}
for(int i = 1;i <= tp;i ++) {
ar[++ ca] = {
st[i],l[st[i]]};
}
tp = 0;
for(int i = ll;i <= rr;i ++) {
if(l[i] >= n || r[i] < 0) continue;
while(tp > 1 && (r[st[tp]]-r[st[tp-1]])*1ll*(i-st[tp]) <= (r[i]-r[st[tp]])*1ll*(st[tp]-st[tp-1])) {
st[tp --] = 0;
}
st[++ tp] = i;
}
for(int i = tp;i > 0;i --) {
ar[++ ca] = {
st[i],r[st[i]]};
}
LL ans = 0;
for(int i = 3;i <= ca;i ++) {
ans += S(ar[1],ar[i-1],ar[i]);
}
AIput(ans,'\n');
return 0;
}
边栏推荐
- C language problems
- C language data type
- Jianmu continuous integration platform v2.5.2 release
- State machine DP 3D
- [flask introduction series] installation and configuration of flask Sqlalchemy
- The new generation of public chain attacks the "Impossible Triangle"
- [paper reading | cryoet] gum net: fast and accurate 3D subtomo image alignment and average unsupervised geometric matching
- Go 事,如何成为一个Gopher ,并在7天找到 Go 语言相关工作,第1篇
- String class
- Basic introduction to pod
猜你喜欢
2022 Shenzhen Cup Title A: get rid of "scream effect" and "echo room effect" and get out of the "information cocoon room"
[freeze electron microscope] analysis of the source code of the subtomogram alignment function of relion4.0 (for self use)
Cs61abc sharing session (VI) detailed explanation of program input and output - standard input and output, file, device, EOF, command line parameters
Solving linear programming problems based on MATLAB
Convert source package to RPM package
Keyboard processing in jetpack compose
The smallest positive number that a subset of an array cannot accumulate
Amaze UI 图标查询
Qt/PyQt 窗口类型与窗口标志
An optimal buffer management scheme with dynamic thresholds paper summary
随机推荐
Effective learning of medical image segmentation annotation based on noise pseudo tags and adversarial learning
Zero technology is deeply involved in the development of privacy computing financial scenario standards of the ICT Institute
Unity beginner 2 - tile making and world interaction (2D)
@JsonSerialize注解的使用
[paper reading | cryoet] gum net: fast and accurate 3D subtomo image alignment and average unsupervised geometric matching
What are the principles and methods of implementing functional automation testing?
Vmstat memory consumption query
FLink CDC 的mysql connector中,mysql的字段是varbinary, 官方
Dilworth theorem
[cryoelectron microscope | paper reading] interpretation of sub fault average m software: multi particle cryo EM refining with M
Keyboard processing in jetpack compose
Unity - default rendering pipeline - sculpt shader
CDM - code division multiplexing (easy to understand)
Character shader exercise
Mutationobserver document learning
Multi thread shopping
准备esp32环境
佳木斯市场监管局开展防疫防虫害专题食品安全网络培训
[cryoelectron microscope] relion4.0 pipeline command summary (self use)
Sqlmap (SQL injection automation tool)