首先特判多边形面积$=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的更多相关文章

  1. 与Google轻轻地擦肩而过

    第一集 因为那几年三天两头往硅谷里飞,所以我实在记不清这个故事到底是发生在98年还是99年夏天某日的一个下午. 那天我和Excite.com的创始人Mark V. H.在Palo Alto的一家餐厅共 ...

  2. Hadoop之父Doug Cutting

    生活中,可能所有人都间接用过他的作品,他是Lucene.Nutch .Hadoop等项目的发起人.是他,把高深莫测的搜索技术形成产品,贡献给普罗大众:还是他,打造了目前在云计算和大数据领域里如日中天的 ...

  3. 关于Hadoop之父Doug Cutting

    生活中,可能所有人都间接用过他的作品,他是Lucene.Nutch .Hadoop等项目的发起人.是他,把高深莫测的搜索技术形成产品,贡献给普罗大众:还是他,打造了目前在云计算和大数据领域里如日中天的 ...

  4. bzoj AC倒序

    Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...

  5. Hadoop之父Doug Cutting:Lucene到Hadoop的开源之路

    Hadoop之父Doug Cutting:Lucene到Hadoop的开源之路 Doug Cutting,凭借自己对工作的热情和脚踏实地的态度,开创了Lucene和Nutch两个成功的开源搜索引擎项目 ...

随机推荐

  1. python3 练手实例1 计算三角形周长和面积

    def j(): a,b,c=map(float,input('请输入三角形三条边的长度,用空格隔开:').split()) if a>0 and b>0 and c>0 and a ...

  2. 更改MySQL密码

    #安装MySQL5.7参考:https://blog.csdn.net/qq_23033339/article/details/80872136#MYSQL的基础操作参考:https://www.cn ...

  3. git本机服务器配置(一):git的安装

    1. 下载git的Windows版本 https://gitforwindows.org/ 2. 安装 点击next 不需要更改,直接点击next 配置git编辑器,我安装了notepad++所以就选 ...

  4. flask学习(二)

    一.蓝图 作用:给开发者提供目录结构 功能:1.自定义模板.静态文件目录 2.给一类url加前缀    3.给一类url添加before_request 目录结构 from flask_werkzur ...

  5. [Kubernetes]关于 Kubernetes ,你想要的,都在这儿了

    陆陆续续,关于 Kubernetes 写了有 20+ 篇文章了. 今天这篇文章来一个整合,从实践到理论,可以按需查看(我是按照博客发表时间来排序的,如果后续有想要更新的内容,也会及时更新到这篇文章中) ...

  6. gym 102059A 树链剖分后odt维护区间

    题意 一棵树 多次修改,每次修改一个点到根的所有边的颜色,并询问现在有哪些颜色染了恰好$m$条边 题解: 稍加思考可以知道,从某个点到根节点的颜色数,均摊复杂度很低,因此,可以考虑珂朵莉树维护重链剖分 ...

  7. LaTex basics

    分节: \section{Supplemental Material}\label{sec:supplemental} 小节: \noindent {\bf Preparing References: ...

  8. go 实现单链表反转

    go实现单链表翻转 package main import "fmt" type ListNode struct { data interface{} Next *ListNode ...

  9. Ubuntu如何安装vncserver

    Ubuntu上安装和配置vncserver,然后通过客户端进行连接,就能够使用图像界面的方式来运行上面的软件了. 1.使用apt-cache search vncserver命令搜索可以用来安装vnc ...

  10. js 字符串切割

    对于字符串的切割截取平时所用可能不是特别多,而且分的比较细,所以自备自查.有备无患. 由于之前所有均在一个demo测试,若是哪里打错了,敬请谅解.一些其余属性找时间继续添加. 1.函数:split() ...