1.处理内容
数据结构部
线段树 1题
树状数组 1题
数学几何部
凸包 1题
旋转卡壳 1题
半平面交 1题
几何基础 1题
皮克定理 1题
平面分治 1题
2.数据结构
(1)线段树练习3
区间修改http://codevs.cn/problem/1082/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define int long long
using namespace std;
inline int read(){
int i=0,f=1;
char ch;
for(ch=getchar();!isdigit(ch);ch=getchar())
if(ch=='-') f=-1;
for(;isdigit(ch);ch=getchar())
i=(i<<1)+(i<<3)+(ch^48);
return i*f;
}
int buf[1024];
inline void write(int x){
if(!x){putchar('0');return ;}
if(x<0){putchar('-');x=-x;}
while(x){buf[++buf[0]]=x%10,x/=10;}
while(buf[0]) putchar(48+buf[buf[0]--]);
return ;
}
#define stan 222222
int n,q,o,a,b,c,val[stan],tag[stan*4],sum[stan*4];
void build(int k,int l,int r){
if(l==r){
sum[k]=val[l];
return ;
}
int mid=l+r>>1;
build(k<<1,l,mid);
build(k<<1|1,mid+1,r);
sum[k]=sum[k<<1]+sum[k<<1|1];
return ;
}
void pushdown(int x,int l,int r){
int mid=l+r>>1;
tag[x<<1]+=tag[x];
tag[x<<1|1]+=tag[x];
sum[x<<1]+=tag[x]*(mid-l+1);
sum[x<<1|1]+=tag[x]*(r-mid);
tag[x]=0;
return ;
}
void update(int k,int l,int r,int x,int y,int c){
if(x<=l&&r<=y){
tag[k]+=c;
sum[k]+=(r-l+1)*c;
return ;
}
if(tag[k])pushdown(k,l,r);
int mid=l+r>>1;
if(x<=mid) update(k<<1,l,mid,x,y,c);
if(y>mid) update(k<<1|1,mid+1,r,x,y,c);
sum[k]=sum[k<<1]+sum[k<<1|1];
return ;
}
int query(int k,int l,int r,int x,int y){
if(x<=l&&r<=y) return sum[k];
if(tag[k]) pushdown(k,l,r);
int mid=l+r>>1,ret=0;
if(x<=mid) ret+=query(k<<1,l,mid,x,y);
if(y>mid) ret+=query(k<<1|1,mid+1,r,x,y);
return ret;
}
signed main(){
n=read();
for(int i=1;i<=n;++i)
val[i]=read();
build(1,1,n);
q=read();
for(int i=1;i<=q;++i){
o=read();
if(o==1){
a=read();b=read();c=read();
update(1,1,n,a,b,c);
}else{
a=read();b=read();
if(a>b) swap(a,b);
write(query(1,1,n,a,b));
puts(" ");
}
}
return 0;
}
(2)线段树练习2
可以直接上树状数组http://codevs.cn/problem/1081/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define int long long
using namespace std;
inline int read(){
int i=0,f=1;
char ch;
for(ch=getchar();!isdigit(ch);ch=getchar())
if(ch=='-') f=-1;
for(;isdigit(ch);ch=getchar())
i=(i<<1)+(i<<3)+(ch^48);
return i*f;
}
int buf[1024];
inline void write(int x){
if(!x){putchar('0');return ;}
if(x<0){putchar('-');x=-x;}
while(x){buf[++buf[0]]=x%10,x/=10;}
while(buf[0]) putchar(48+buf[buf[0]--]);
return ;
}
#define stan 111111
int n,q,o,a,b,c,val[stan],data[stan];
void insert(int x,int v){
while(x<=n){
data[x]+=v;
x+=(x&(-x));
}
return ;
}
int query(int x){
int ret=0;
while(x){
ret+=data[x];
x-=(x&(-x));
}
return ret;
}
signed main(){
n=read();
for(int i=1;i<=n;++i){
val[i]=read();
insert(i,val[i]);
}
q=read();
for(int i=1;i<=q;++i){
o=read();
if(o==1){
a=read();b=read();c=read();
for(int j=a;j<=b;++j)
insert(j,c);
}else{
a=read();
write(query(a)-query(a-1));
puts(" ");
}
}
return 0;
}
3.数学几何部
(1)圈奶牛
求最大凸包周长http://www.cogs.pro/cogs/problem/problem.php?pid=896
提供两种极角排序算法
algorithm1.graham-scan
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define int long long
#define eps 1e-7
using namespace std;
inline int read(){
int i=0,f=1;
char ch;
for(ch=getchar();!isdigit(ch);ch=getchar())
if(ch=='-') f=-1;
for(;isdigit(ch);ch=getchar())
i=(i<<1)+(i<<3)+(ch^48);
return i*f;
}
int buf[1024];
inline void write(int x){
if(!x){putchar('0');return ;}
if(x<0){putchar('-');x=-x;}
while(x){buf[++buf[0]]=x%10,x/=10;}
while(buf[0]) putchar(48+buf[buf[0]--]);
return ;
}
#define stan 11111
struct P{
double x,y;
}p[stan],q[stan];
int n,top,order[stan];
double ans;
P vec(const P &a,const P &b){
P q;
q.x=a.x-b.x;
q.y=a.y-b.y;
return q;
}
double xplus(P a,P b){
return a.x*b.y-a.y*b.x;
}
double dotplus(P a){
return a.x*a.x+a.y*a.y;
}
bool cmp(int a,int b){
int x=xplus(vec(p[a],p[1]),vec(p[b],p[1]));
if(x!=0) return x>0;
else return dotplus(vec(p[a],p[1]))1&&xplus(vec(p[u],q[top-1]),vec(q[top],q[top-1]))>=0) --top;
q[++top]=p[u];
}
for(int i=1;i2) ans+=dist(q[1],q[top]);
return ;
}
signed main(){
//freopen("fc.in","r",stdin);
//freopen("fc.out","w",stdout);
n=read();
for(int i=1;i<=n;++i)
scanf("%lf%lf",&p[i].x,&p[i].y);
graham();
printf("%.2lf",ans);
return 0;
}
algorithm2.鸡肋的melkman
据说是在线,但并不会用在线版
思想:在当前点有序的情况下,维护一个支持两端插入/删除的队列
总觉得和graham没什么区别...
wuvin大佬也是这么觉得的....
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define int long long
#define eps 1e-7
using namespace std;
inline int read(){
int i=0,f=1;
char ch;
for(ch=getchar();!isdigit(ch);ch=getchar())
if(ch=='-') f=-1;
for(;isdigit(ch);ch=getchar())
i=(i<<1)+(i<<3)+(ch^48);
return i*f;
}
int buf[1024];
inline void write(int x){
if(!x){putchar('0');return ;}
if(x<0){putchar('-');x=-x;}
while(x){buf[++buf[0]]=x%10,x/=10;}
while(buf[0]) putchar(48+buf[buf[0]--]);
return ;
}
#define stan 11111
struct P{
double x,y;
}p[stan],q[stan*2];
int n,top,order[stan],guideb,guidet;
double ans;
P vec(const P &a,const P &b){
P q;
q.x=a.x-b.x;
q.y=a.y-b.y;
return q;
}
double xplus(P a,P b){
return a.x*b.y-a.y*b.x;
}
double dotplus(P a){
return a.x*a.x+a.y*a.y;
}
bool cmp(int a,int b){
int x=xplus(vec(p[a],p[1]),vec(p[b],p[1]));
if(x!=0) return x>0;
else return dotplus(vec(p[a],p[1]))1&&xplus(vec(p[u],q[guidet-1]),vec(q[guidet],q[guidet-1]))>=eps) --guidet;
q[++guidet]=p[u];
while(guidet-guideb>1&&xplus(vec(q[guideb],q[guideb+1]),vec(p[u],q[guideb+1]))>=-eps) ++guideb;
q[--guideb]=p[u];
}
for(int i=guideb;i
(2)最大土地面积(SCOI2007)
在凸包的基础上枚举对角线http://www.lydsy.com/JudgeOnline/problem.php?id=1069
同样提供两种极角排序的凸包算法
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define int long long
#define eps 1e-7
using namespace std;
inline int read(){
int i=0,f=1;
char ch;
for(ch=getchar();!isdigit(ch);ch=getchar())
if(ch=='-') f=-1;
for(;isdigit(ch);ch=getchar())
i=(i<<1)+(i<<3)+(ch^48);
return i*f;
}
int buf[1024];
inline void write(int x){
if(!x){putchar('0');return ;}
if(x<0){putchar('-');x=-x;}
while(x){buf[++buf[0]]=x%10,x/=10;}
while(buf[0]) putchar(48+buf[buf[0]--]);
return ;
}
#define stan 11111
struct P{
double x,y;
}p[stan],q[stan*2],r[stan];
int n,top,order[stan],guideb,guidet;
double ans;
P vec(const P &a,const P &b){
P q;
q.x=a.x-b.x;
q.y=a.y-b.y;
return q;
}
double xplus(P a,P b){
return a.x*b.y-a.y*b.x;
}
double dotplus(P a){
return a.x*a.x+a.y*a.y;
}
bool cmp(int a,int b){
double x=xplus(vec(p[a],p[1]),vec(p[b],p[1]));
if(x!=0) return x>0;
else return dotplus(vec(p[a],p[1]))1&&xplus(vec(p[u],q[guidet-1]),vec(q[guidet],q[guidet-1]))>=-eps) --guidet;
q[++guidet]=p[u];
while(guidet-guideb>1&&xplus(vec(q[guideb],q[guideb+1]),vec(p[u],q[guideb+1]))>=-eps) ++guideb;
q[--guideb]=p[u];
}
top=0;
for(int i=guideb;i1&&xplus(vec(p[u],q[top-1]),vec(q[top],q[top-1]))>=0) --top;
q[++top]=p[u];
}
for(int i=1;i<=top;++i)
r[i]=q[i];
return ;
}
int ahead(int x){
if(x==top) return 1;
else return x+1;
}
void solve(){
ans=0.000;
for(int i=1;i<=top;++i){
double s1,s2;
for(int q1=ahead(i),j=ahead(q1),q2=ahead(j);j
(3)瞭望塔(ZJOI2008)
著名的半平面交样板
甩链接吧还是http://www.lydsy.com/JudgeOnline/problem.php?id=1038
感兴趣者可以再拿byvoid大佬的大灾变做一做找自信https://www.byvoid.com/zhs/blog/cataclysm-problem
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define int long long
#define double long double
#define eps 1e-7
using namespace std;
inline int read(){
int i=0,f=1;
char ch;
for(ch=getchar();!isdigit(ch);ch=getchar())
if(ch=='-') f=-1;
for(;isdigit(ch);ch=getchar())
i=(i<<1)+(i<<3)+(ch^48);
return i*f;
}
int buf[1024];
inline void write(int x){
if(!x){putchar('0');return ;}
if(x<0){putchar('-');x=-x;}
while(x){buf[++buf[0]]=x%10,x/=10;}
while(buf[0]) putchar(48+buf[buf[0]--]);
return ;
}
#define stan 3333
struct P{
double x,y;
}p[stan],a[stan];
int n,cnt,tot;
double ans;
P vec(const P &a,const P &b){
P q;
q.x=a.x-b.x;
q.y=a.y-b.y;
return q;
}
double xplus(P a,P b){
return a.x*b.y-a.y*b.x;
}
double dotplus(P a){
return a.x*a.x+a.y*a.y;
}
struct L{
P a,b;
double slope;
friend bool operator <(L x,L y){
if(x.slope!=y.slope) return x.slope0;
}
}l[stan],que[stan];
P inter(L x,L y){
double k1,k2,t;
k1=xplus(vec(y.b,x.a),vec(x.b,x.a));
k2=xplus(vec(x.b,x.a),vec(y.a,x.a));
t=k1/(k1+k2);
P ret;
ret.x=y.b.x+t*(y.a.x-y.b.x);
ret.y=y.b.y+t*(y.a.y-y.b.y);
return ret;
}
bool check(L a,L b,L t){
P s=inter(a,b);
return xplus(vec(t.b,t.a),vec(s,t.a))<0;
}
void preact(){
p[0].x=p[1].x;p[0].y=999999;
p[n+1].x=p[n].x;p[n+1].y=999999;
for(int i=1;i<=n;++i){
l[++cnt].a=p[i-1];l[cnt].b=p[i];
l[++cnt].a=p[i];l[cnt].b=p[i+1];
}
for(int i=1;i<=cnt;++i)
l[i].slope=atan2(l[i].b.y-l[i].a.y,l[i].b.x-l[i].a.x);
sort(l+1,l+cnt+1);
return ;
}
void hpi(){
int ll=1,rr=0;tot=0;
for(int i=1;i<=cnt;++i){
if(l[i].slope!=l[i-1].slope) ++tot;
l[tot]=l[i];
}
cnt=tot,tot=0;
que[++rr]=l[1];que[++rr]=l[2];
for(int i=3;i<=cnt;++i){
while(ll=p[j].x&&a[i].x<=p[j+1].x)
ans=min(ans,a[i].y-inter((L){p[j],p[j+1]},(L){u,a[i]}).y);
}
for(int i=1;i<=n;++i){
P u;
u.x=p[i].x;u.y=-1;
for(int j=1;j=a[j].x&&p[i].x<=a[j+1].x)
ans=min(ans,inter((L){a[j],a[j+1]},(L){u,p[i]}).y-p[i].y);
}
return ;
}
signed main(){
ans=1e60;
n=read();
for(int i=1;i<=n;++i)
p[i].x=read();
for(int i=1;i<=n;++i)
p[i].y=read();
preact();
hpi();
getans();
printf("%.3Lf",ans);
return 0;
}
(4)segments
这个题反正可以转化为求与所有线段相交的直线http://poj.org/problem?id=3304
至于复杂度,O(n^3)可以轻松过100
怎么判?用差乘判
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define eps 1e-8
using namespace std;
inline int read(){
int i=0,f=1;
char ch;
for(ch=getchar();!isdigit(ch);ch=getchar())
if(ch=='-') f=-1;
for(;isdigit(ch);ch=getchar())
i=(i<<1)+(i<<3)+(ch^48);
return i*f;
}
int buf[1024];
inline void write(int x){
if(!x){putchar('0');return ;}
if(x<0){putchar('-');x=-x;}
while(x){buf[++buf[0]]=x%10,x/=10;}
while(buf[0]) putchar(48+buf[buf[0]--]);
return ;
}
#define stan 1111111
struct P{
double x,y;
}p[stan];
int n,cnt,tot,T,tag;
double ans;
P vec(const P &a,const P &b){
P q;
q.x=a.x-b.x;
q.y=a.y-b.y;
return q;
}
double xplus(P a,P b){
return a.x*b.y-a.y*b.x;
}
double dotplus(P a){
return a.x*a.x+a.y*a.y;
}
struct L{
P a,b;
double slope;
friend bool operator <(L x,L y){
if(x.slope!=y.slope) return x.slope0;
}
}l[stan],que[stan];
P inter(L x,L y){
double k1,k2,t;
k1=xplus(vec(y.b,x.a),vec(x.b,x.a));
k2=xplus(vec(x.b,x.a),vec(y.a,x.a));
t=k1/(k1+k2);
P ret;
ret.x=y.b.x+t*(y.a.x-y.b.x);
ret.y=y.b.y+t*(y.a.y-y.b.y);
return ret;
}
bool check(P a,P b){
if(fabs(a.x-b.x)eps) return false;
return true;
}
signed main(){
T=read();
while(T--){
n=read();
for(int i=1;i<=n;++i)
scanf("%lf%lf%lf%lf",&l[i].a.x,&l[i].a.y,&l[i].b.x,&l[i].b.y);
tag=true;
if(n<3) tag=false;
for(int i=1;i<=n&&tag;++i){
if(check(l[i].a,l[i].b)) tag=false;
for(int j=i+1;j<=n&&tag;++j){
if(check(l[i].a,l[j].a)) tag=false;
else if(check(l[i].b,l[j].a)) tag=false;
else if(check(l[i].a,l[j].b)) tag=false;
else if(check(l[i].b,l[j].b)) tag=false;
}
}
if(tag)
puts("No!");
else
puts("Yes!");
}
return 0;
}
(5)Triangle
一个多边形的顶点如果全是格点
则有 2S=2a+b-2
其中S是多边形面积,a是多边形内部格点数,b是多边形上的格点数
至于如何求S,差乘即可
至于如何求b,求gcd即可
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
inline int read(){
int i=0,f=1;
char ch;
for(ch=getchar();!isdigit(ch);ch=getchar())
if(ch=='-') f=-1;
for(;isdigit(ch);ch=getchar())
i=(i<<1)+(i<<3)+(ch^48);
return i*f;
}
int buf[1024];
inline void write(int x){
if(!x){putchar('0');return ;}
if(x<0){putchar('-');x=-x;}
while(x){buf[++buf[0]]=x%10,x/=10;}
while(buf[0]) putchar(48+buf[buf[0]--]);
return ;
}
int a,b,c,d,e,f,B,S;
int gcd(int a,int b){
if(b) return gcd(b,a%b);
return a;
}
signed main(){
a=read();b=read();c=read();d=read();e=read();f=read();
while(a||b||c||d||e||f){
B=0;S=0;
B+=gcd(abs(a-c),abs(b-d));
B+=gcd(abs(c-e),abs(d-f));
B+=gcd(abs(e-a),abs(f-b));
S=abs((c-a)*(f-b)-(e-a)*(d-b));
write((S+2-B)/2);
puts(" ");
a=read();b=read();c=read();d=read();e=read();f=read();
}
}
(6)Quoit Design
很神奇的O(nlogn)分治
先预处理两块之间的分界线,递归的结果在x轴框一个范围
然后对于合法点,再在y轴框一个范围
处理之后递归
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define eps 1e-7
using namespace std;
inline int read(){
int i=0,f=1;
char ch;
for(ch=getchar();!isdigit(ch);ch=getchar())
if(ch=='-') f=-1;
for(;isdigit(ch);ch=getchar())
i=(i<<1)+(i<<3)+(ch^48);
return i*f;
}
int buf[1024];
inline void write(int x){
if(!x){putchar('0');return ;}
if(x<0){putchar('-');x=-x;}
while(x){buf[++buf[0]]=x%10,x/=10;}
while(buf[0]) putchar(48+buf[buf[0]--]);
return ;
}
#define stan 1111111
struct P{
double x,y;
}p[stan];
int n,cnt,tot;
double ans;
P vec(const P &a,const P &b){
P q;
q.x=a.x-b.x;
q.y=a.y-b.y;
return q;
}
double xplus(P a,P b){
return a.x*b.y-a.y*b.x;
}
double dotplus(P a){
return a.x*a.x+a.y*a.y;
}
bool cmp(P a,P b){
return a.x>1;
double lx=(p[mid].x+p[mid+1].x)/2.0;
double dis=min(solve(l,mid),solve(mid+1,r));
static P pre[stan],suf[stan],tmp[stan];
int x=l,y=mid+1,nop=0,nos=0;
for(int i=l;i<=r;++i){
if(x<=mid&&(y==r+1||p[x].ytmp[i].x)
suf[++nos]=tmp[i];
}
}
for(int i=l;i<=r;++i)
p[i]=tmp[i];
for(int i=1,j=1;i<=nop||j<=nos;){
if(i<=nop&&(j>nos||pre[i].y=suf[k].y) break;
dis=min(dis,dist(pre[i],suf[k]));
}
++i;
}else{
for(int k=i-1;k;--k){
if(suf[j].y-dis>=pre[k].y) break;
dis=min(dis,dist(pre[k],suf[j]));
}
++j;
}
}
return dis;
}
signed main(){
while(n=read(),n!=0){
for(int i=1;i<=n;++i)
scanf("%lf%lf",&p[i].x,&p[i].y);
sort(p+1,p+n+1,cmp);
printf("%.2lf\n",solve(1,n)/2.0);
}
return 0;
}
局部完结撒花