9.7联合作战战果

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;
}
局部完结撒花



你可能感兴趣的:(OI,半平面交科,分治纲,线段树科,数据结构门)