BZOJ3592 : Architext
首先特判多边形面积$=0$的情况,此时内部没有点,答案只会在顶点处取到。
对于面积$>0$的情况,离线询问,将所有多边形合在一起得到平面图,然后求出对偶图,那么每条多边形边的两侧分别对应对偶图中两个域。
每个多边形把这些域分成内外两个连通块,也就是保留除了多边形边之外的所有边后对偶图的连通情况。
把每个点随便放在所在的某个域之中,按时间分治,维护按秩合并的并查集。
对于每个询问任取一条多边形边,它两侧分别是域$A$和域$B$。那么有且仅有一个不与无穷域连通,假设是$A$,那么答案就是$A$所在连通块的信息。这会漏掉一些因为随便指派而不在连通块内的顶点。遍历每个顶点$x$,判断$x$所在域所在连通块是否和无穷域连通,是的话再把$x$的信息加入答案即可。
时间复杂度$O(n\log^2n)$。
#include<cstdio>
#include<cmath>
#include<set>
#include<algorithm>
#include<map>
#include<vector>
using namespace std;
typedef pair<int,int>PI;
typedef long long ll;
const int N=50010,M=320010;
int Case,n,m,cq,cnt,i,j,k,x,y,z,q[N],at[N];
map<PI,int>idx;
int que[N][3];
vector<int>pool[N];
int dep[M],f[M],sum[M],mx[M],val[N];
int laste[M],lastv[N];
int co,op[N*3+M*2][3];
int MX,SUM;
struct EV{
char op;int x,y,l,r;
EV(){}
EV(char _op,int _x,int _y,int _l,int _r){op=_op,x=_x,y=_y,l=_l,r=_r;}
};
typedef vector<EV>V;
struct P{
int x,y,d;
ll operator*(const P&b){return 1LL*x*b.y-1LL*y*b.x;}
}a[N];
struct E{
int x,y;double o;
E(){}
E(int _x,int _y){x=_x,y=_y,o=atan2(a[y].x-a[x].x,a[y].y-a[x].y);}
}e[M];
bool del[M];int from[M];
namespace GetArea{
struct cmp{bool operator()(int a,int b){return e[a].o<e[b].o;}};
set<int,cmp>g[N];set<int,cmp>::iterator k;int i,j,q[M],t;
void work(){
for(i=0;i<m+m;i++)if(!del[i]){
for(q[t=1]=j=i;;q[++t]=j=*k){
k=g[e[j].y].find(j^1);k++;
if(k==g[e[j].y].end())k=g[e[j].y].begin();
if(*k==i)break;
}
ll s=0;
for(j=1;j<=t;j++)s+=a[e[q[j]].x]*a[e[q[j]].y],del[q[j]]=1;
if(s<=0)continue;
for(cnt++,j=1;j<=t;j++){
from[q[j]]=cnt;
at[e[q[j]].x]=at[e[q[j]].y]=cnt;
}
}
}
}
inline void newedge(int x,int y){
if(idx.find(PI(x,y))!=idx.end())return;
if(idx.find(PI(y,x))!=idx.end())return;
e[m<<1]=E(x,y);
e[m<<1|1]=E(y,x);
idx[PI(x,y)]=idx[PI(y,x)]=m++;
}
inline int getid(int x,int y){return idx[PI(x,y)];}
int F(int x){return f[x]==x?x:F(f[x]);}
inline void merge(int x,int y){
x=F(x),y=F(y);
if(x==y)return;
if(dep[x]==dep[y]){
co++;
op[co][0]='d';
op[co][1]=x;
dep[x]++;
}
if(dep[x]<dep[y])swap(x,y);
co++;
op[co][0]='f';
op[co][1]=y;
f[y]=x;
if(mx[y]>mx[x]){
co++;
op[co][0]='m';
op[co][1]=x;
op[co][2]=mx[x];
mx[x]=mx[y];
}
co++;
op[co][0]='s';
op[co][1]=x;
op[co][2]=sum[y];
sum[x]+=sum[y];
}
inline void ins(int x,int y){
int z=F(at[x]);
co++;
op[co][0]='v';
op[co][1]=x;
op[co][2]=val[x];
val[x]=y;
if(y>mx[z]){
co++;
op[co][0]='m';
op[co][1]=z;
op[co][2]=mx[z];
mx[z]=y;
}
co++;
op[co][0]='s';
op[co][1]=z;
op[co][2]=y;
sum[z]+=y;
}
inline void retrace(int t){
while(co>t){
if(op[co][0]=='d')dep[op[co][1]]--;
else if(op[co][0]=='f')f[op[co][1]]=op[co][1];
else if(op[co][0]=='v')val[op[co][1]]=op[co][2];
else if(op[co][0]=='m')mx[op[co][1]]=op[co][2];
else sum[op[co][1]]-=op[co][2];
co--;
}
}
inline void up(int&a,int b){a<b?(a=b):0;}
void solve(int l,int r,V v){
int pos=co,mid=(l+r)>>1;
V vl,vr;
for(V::iterator it=v.begin();it!=v.end();it++){
if(it->l<=l&&r<=it->r){
if(it->op=='E')merge(it->x,it->y);
else ins(it->x,it->y);
}else{
if(it->l<=mid)vl.push_back(*it);
if(it->r>mid)vr.push_back(*it);
}
}
if(l==r){
if(que[l][0]==1){
int j,o,u,k=que[l][1];
for(j=0;j<k;j++)q[j]=pool[l][j];
q[k]=q[0];
MX=SUM=0;
if(que[l][2]){
for(j=0;j<k;j++){
o=q[j];
SUM+=val[o];
up(MX,val[o]);
}
}else{
o=getid(q[0],q[1])<<1;
u=from[o];
if(F(u)==F(0))u=from[o|1];
u=F(u);
SUM=sum[u];
MX=mx[u];
for(j=0;j<k;j++){
o=q[j];
if(F(at[o])!=u){
SUM+=val[o];
up(MX,val[o]);
}
}
}
printf("%d %d\n",SUM,MX);
}
retrace(pos);
return;
}
solve(l,mid,vl);
solve(mid+1,r,vr);
retrace(pos);
}
int main(){
scanf("%d%d",&Case,&n);
for(i=1;i<=n;i++)scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].d);
scanf("%d",&cq);
if(!cq)return 0;
for(i=1;i<=cq;i++){
char op[5];
scanf("%s",op);
if(op[0]=='H')scanf("%d%d",&que[i][1],&que[i][2]);
else{
que[i][0]=1;
scanf("%d",&k);
que[i][1]=k;
for(j=0;j<k;j++)scanf("%d",&q[j]);
q[k]=q[0];
for(j=0;j<k;j++)newedge(q[j],q[j+1]);
pool[i].resize(k);
for(j=0;j<k;j++)pool[i][j]=q[j];
}
}
for(i=0;i<m+m;i++)GetArea::g[e[i].x].insert(i);
GetArea::work();
V v;
for(i=1;i<=n;i++)lastv[i]=1;
for(i=1;i<=cq;i++){
if(que[i][0]==0){
x=que[i][1];
y=lastv[x];
if(y<=i-1)v.push_back(EV('V',x,a[x].d,y,i-1));
a[x].d+=que[i][2];
lastv[x]=i;
}else{
k=que[i][1];
for(j=0;j<k;j++)q[j]=pool[i][j];
q[k]=q[0];
ll s=0;
for(j=0;j<k;j++)s+=a[q[j]]*a[q[j+1]];
if(s<0){
for(j=0;j<k;j++){
x=getid(q[j],q[j+1]);
y=laste[x];
if(y+1<=i-1)v.push_back(EV('E',from[x<<1],from[x<<1|1],y+1,i-1));
laste[x]=i;
}
}else que[i][2]=1;
}
}
for(i=1;i<=n;i++)v.push_back(EV('V',i,a[i].d,lastv[i],cq));
for(i=0;i<=cnt;i++)f[i]=i;
for(i=0;i<m;i++){
y=laste[i];
if(y+1<=cq)v.push_back(EV('E',from[i<<1],from[i<<1|1],y+1,cq));
}
solve(1,cq,v);
return 0;
}
BZOJ3592 : Architext的更多相关文章
- 与Google轻轻地擦肩而过
第一集 因为那几年三天两头往硅谷里飞,所以我实在记不清这个故事到底是发生在98年还是99年夏天某日的一个下午. 那天我和Excite.com的创始人Mark V. H.在Palo Alto的一家餐厅共 ...
- Hadoop之父Doug Cutting
生活中,可能所有人都间接用过他的作品,他是Lucene.Nutch .Hadoop等项目的发起人.是他,把高深莫测的搜索技术形成产品,贡献给普罗大众:还是他,打造了目前在云计算和大数据领域里如日中天的 ...
- 关于Hadoop之父Doug Cutting
生活中,可能所有人都间接用过他的作品,他是Lucene.Nutch .Hadoop等项目的发起人.是他,把高深莫测的搜索技术形成产品,贡献给普罗大众:还是他,打造了目前在云计算和大数据领域里如日中天的 ...
- bzoj AC倒序
Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...
- Hadoop之父Doug Cutting:Lucene到Hadoop的开源之路
Hadoop之父Doug Cutting:Lucene到Hadoop的开源之路 Doug Cutting,凭借自己对工作的热情和脚踏实地的态度,开创了Lucene和Nutch两个成功的开源搜索引擎项目 ...
随机推荐
- Spring rabbitMq 中 correlationId或CorrelationIdString 消费者获取为null的问题
问题 在用Spring boot 的 spring-boot-starter-amqp 快速启动 rabbitMq 是遇到了个坑 消费者端获取不到:correlationId或Correlatio ...
- XGBoost参数调优完全指南
简介 如果你的预测模型表现得有些不尽如人意,那就用XGBoost吧.XGBoost算法现在已经成为很多数据工程师的重要武器.它是一种十分精致的算法,可以处理各种不规则的数据.构造一个使用XGBoost ...
- data_summarize.pl data目录文本时长汇总脚本
#!/usr/bin/env perl # Copyright 2018 Jarvan Wang if (@ARGV != 1) { #print STDERR "Usage: keywor ...
- 更改checkbox的默认样式
最近做一个vue项目要用到checkbox要修改默认样式,选中是纯白色,不选择只有白色边框,起初以为很容易,没想到还折腾了一翻,记录一下. 几经折腾,理清input 和label的关系 最终改进版本, ...
- javascript获取当前域名
<script language="javascript">//获取域名host = window.location.host;host2=document.domai ...
- iframe 加form提交数据
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- winform倒计时
public partial class Form1 : Form { private int Seconds; public Form1() { InitializeComponent(); // ...
- OpenStack—nova组件计算服务
nova介绍: Nova 是 OpenStack 最核心的服务,负责维护和管理云环境的计算资源.OpenStack 作为 IaaS 的云操作系统,虚拟机生命周期管理也就是通过 Nova 来实现的. 用 ...
- 算法工程师<数学题/智力题>
<数学题/智力题> 1.如果一个女生说,她集齐了十二个星座的前男友,我们应该如何估计她前男友的数量? https://blog.csdn.net/FnqTyr45/article/deta ...
- php 获取用户的IP、地址、来源
js方法获取用户的 ip 和 地址 <script src="http://pv.sohu.com/cityjson?ie=utf-8"></script> ...