首先特判多边形面积$=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两个成功的开源搜索引擎项目 ...
随机推荐
-
sql篇 select from where group by having order by
以前,自己总是记不住如何用group by,如何用order by,什么时候用group by,什么时候用order by,什么时候两者一起用,怎么用,谁先谁后,现在,我们就一起来说一下Select ...
-
OAUTH 协议介绍
OAUTH 产生背景 随着互联网的深入发展,一些互联网巨头积累了海量的用户和数据.对于平台级软件厂商来说,用户的需求多种多样,变化万千 以一己之力予以充分满足,难免疲于本命.因此将数据以接口的形式开放 ...
-
grid编辑后时间格式不对问题
在column中应该定义xtype和format格式: xtype: 'datecolumn', format:'Y-m-d' 之后正常
-
Java中多态的理解
最近学习Java里面的多态下面是个人的整理: 多态存在的3个必要条件: 1.要有继承 2.要有方法的重写 3.父类引用指向子类对象(对于父类中定义的方法,如果子类中重写了该方法,那么父类类型的引用将会 ...
-
ASP.NET Core MVC应用程序中的后台工作任务
在应用程序的内存中缓存常见数据(如查找)可以显着提高您的MVC Web应用程序性能和响应时间.当然,这些数据必须定期刷新. 当然你可以使用任何方法来更新数据,例如Redis中就提供了设定缓存对象的生命 ...
-
Oracle中计算两个日期时间的差
--方法1 select floor((sysdate - to_date('2006-09-01 08:00:00', 'yyyy-mm-dd hh24:mi:ss'))) as sDays fro ...
-
Java之修改文件内容:字符串逐行替换
依赖包: <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</a ...
-
C#中Post请求的两种方式发送参数链和Body的
POST请求 有两种方式 一种是组装key=value这种参数对的方式 一种是直接把一个字符串发送过去 作为body的方式 我们在postman中可以看到 sfdsafd sdfsdfds publi ...
-
Active Directory中获取域管理员权限的攻击方法
Active Directory中获取域管理员权限的攻击方法 译:by backlion 0x00 前言 攻击者可以通过多种方式在Active Directory中获得域管理员权限, ...
- zookeeper入门到精通