zoukankan      html  css  js  c++  java
  • ! HNOI2016矿区



    平面图转对偶图(把面转为点,点转为面)

    构建方法:

    1. 双向边变两个单向边,这样每条边属于一个面,把每个点的出边按极角排序
    2. 从一条边出发,不停找下一条边(下一个点向左旋,离我最近的边),最后会形成一块区域。不停找,把所有区域找出来

    然后以无域界为根(叉积算出为负)建立一棵生成树

    然后就是非常妙的地方了

    查询时,一次遍历每条边,若不在树上则跳过,否则若这条边所在的面是儿子就加上子树面积,否则减去

    #include<bits/stdc++.h>
    using namespace std;
    #define int long long 
    inline int read(){
    	int x=0,f=1;char c=getchar();
    	while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
    	while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
    	return f==1?x:-x;
    }
    const int N=2e5+4,M=12e5+4;
    const double eps=1e-6;
    struct poin{
    	int x,y;
    	inline poin operator -(const poin &a)const{
    		return (poin){x-a.x,y-a.y};
    	}
    	inline int operator *(const poin &a)const{
    		return x*a.y-y*a.x;
    	}
    };
    struct edge{
    	int id,u,v;
    	double sl;
    	inline bool operator <(const edge &x)const{
    		return fabs(sl-x.sl)<eps?v<x.v:sl<x.sl;
    	}
    };
    vector<edge>h[N],t[M];
    edge e[M];
    poin p[N];
    int n,m,Q,rt,cnt=1,cn,ans1,ans2;
    int nxt[M],bel[M],vis[M],fa[M],ins[M],s[M],s2[M],z[N];
    inline void add(int u,int v){
    	e[++cnt]=(edge){cnt,u,v,atan2(p[v].y-p[u].y,p[v].x-p[u].x)};
    	h[u].push_back(e[cnt]);
    }
    inline void build(){
    	for(int i=1;i<=n;i++)sort(h[i].begin(),h[i].end());
    	for(int i=2,v;i<=cnt;i++){
    		v=e[i].v;
    		auto it=lower_bound(h[v].begin(),h[v].end(),e[i^1]);
    		if(it==h[v].begin())it=h[v].end();
    		nxt[i]=(*--it).id;
    	}
    	for(int i=2;i<=cnt;i++){
    		if(bel[i])continue;
    		++cn;
    		for(int j=i;!bel[j];bel[j]=cn,j=nxt[j])
    			s[cn]+=p[e[j].u]*p[e[j].v];
    		if(s[cn]<=0)rt=cn;
    	}
    	for(int i=2;i<=cnt;i++)
    		t[bel[i]].push_back((edge){i,bel[i],bel[i^1]});
    }
    int gcd(int x,int y){
    	return y==0?x:gcd(y,x%y);
    }
    void dfs(int x){
    	s2[x]=s[x]*s[x];s[x]<<=1;
    	vis[x]=1;
    	for(auto i:t[x]){
    		if(vis[i.v])continue;
    		fa[i.v]=x;
    		ins[i.id]=ins[i.id^1]=1;
    		dfs(i.v);
    		s2[x]+=s2[i.v];
    		s[x]+=s[i.v];
    	}
    }
    signed main(){
    	n=read();m=read();Q=read();
    	for(int i=1;i<=n;i++){
    		p[i].x=read();p[i].y=read();
    	}
    	for(int i=1,u,v;i<=m;i++){
    		u=read();v=read();
    		add(u,v);add(v,u);
    	}
    	build();
    	dfs(rt);
    	int d,u,v,j,gd;
    	edge x;
    	while(Q--){
    		d=(read()+ans2)%n+1;
    		for(int i=1;i<=d;i++)z[i]=(read()+ans2)%n+1;
    		z[d+1]=z[1];
    		ans1=ans2=0;
    		for(int i=1;i<=d;i++){
    			u=z[i];v=z[i+1];
    			x=(edge){0,u,v,atan2(p[v].y-p[u].y,p[v].x-p[u].x)};
    			auto it=lower_bound(h[u].begin(),h[u].end(),x);
    			j=(*it).id;
    			if(!ins[j])continue;
    			if(fa[bel[j]]==bel[j^1]){ans1+=s[bel[j]];ans2+=s2[bel[j]];}
    			else{ans1-=s[bel[j^1]];ans2-=s2[bel[j^1]];}
    		}
    		gd=gcd(ans1,ans2);
    		ans1/=gd;ans2/=gd;
    		cout<<ans2<<" "<<ans1<<"
    ";
    	}
    	return (0-0);
    }
    
  • 相关阅读:
    lambba表达式
    根据某个字段筛选list数据
    git和idea绑定
    gitee创建仓库
    用 Python 3 + PyQt5 擼了一個可以播放“任意”音樂的播放器
    zabbix 共享内存设置
    Zabbix高可用,实现zabbix的无缝切换,无故障时间
    python练习题100
    斐波那契数列python实现
    随机生成指定位数密码包括大小写数字特殊符号
  • 原文地址:https://www.cnblogs.com/aurora2004/p/12657974.html
Copyright © 2011-2022 走看看