zoukankan      html  css  js  c++  java
  • [BZOJ4541] [HNOI2016] 矿区

    题目链接

    BZOJ:https://lydsy.com/JudgeOnline/problem.php?id=4541.

    LOJ:https://loj.ac/problem/2052.

    洛谷:https://www.luogu.org/problemnew/show/P3249.

    Solution

    平面图转对偶图。

    平面图转对偶图大概就是说,对于一个平面图,它把平面分割成了若干个区块,对于每个区块抽象成一个点,原图上的分割两个区块的边转化成连接两个点的边,转化完之后的图就叫对偶图。

    对于这道题,我们先把对偶图弄出来,随便整一棵生成树,对于每个点我们记录当前区块的面积的平方。

    然后对于询问我们逆时针扫描这个图,然后对经过的边分析,如果当前边为非树边就不管,否则我们可以随便定义一个正方向,如果当前边是儿子指向父亲则ans+=s[son](s[x])表示(x)子树的点权和,否则ans-=s[son]

    你画个图就能明白了,具体的我也不会证

    具体见代码

    #include<bits/stdc++.h>
    using namespace std;
    
    void read(int &x) {
        x=0;int f=1;char ch=getchar();
        for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f;
        for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f;
    }
    
    void print(int x) {
        if(x<0) putchar('-'),x=-x;
        if(!x) return ;print(x/10),putchar(x%10+48);
    }
    void write(int x) {if(!x) putchar('0');else print(x);putchar('
    ');}
    
    #define lf double
    #define ll long long 
    
    const int maxn = 2e6+10;
    const int inf = 1e9;
    const lf eps = 1e-8;
    
    struct P {
    	int x,y;
    	P operator - (const P &rhs) const {return (P){x-rhs.x,y-rhs.y};}
    	ll operator * (const P &rhs) const {return 1ll*x*rhs.y-1ll*y*rhs.x;}
    }p[maxn];
    
    ll gcd(ll a,ll b) {return !b?a:gcd(b,a%b);}
    
    struct edge{
    	int u,v,id;lf ang;
    	edge() {}
    	edge(int _u,int _v) {u=_u,v=_v,ang=atan2(p[v].y-p[u].y,p[v].x-p[u].x);}
    	bool operator < (const edge &rhs) const {return ang<rhs.ang;}
    }a[maxn];
    
    vector <edge > e[maxn];
    
    int n,m,Q,nxt[maxn],tot=1,bel[maxn],cnt,rt,f[maxn],in[maxn],tr[maxn];
    ll s2[maxn],ans,val[maxn];
    
    int find(int x) {return f[x]==x?x:f[x]=find(f[x]);}
    
    void ins(int u,int v) {a[++tot]=edge(u,v),a[tot].id=tot;e[u].push_back(a[tot]);}
    
    struct Tree {
    	int head[maxn],tot,fa[maxn];
    	struct Edge{int to,nxt;}e[maxn<<1];
    
    	void add(int u,int v) {e[++tot]=(Edge){v,head[u]},head[u]=tot;}
    	void ins(int u,int v) {add(u,v),add(v,u);}
    	
    	void dfs(int x,int F) {
    		fa[x]=F,s2[x]=val[x];
    		for(int i=head[x];i;i=e[i].nxt)
    			if(e[i].to!=fa[x]) dfs(e[i].to,x),s2[x]+=s2[e[i].to];
    	}
    }T;
    
    void prepare() {
    	for(int i=1;i<=n;i++) sort(e[i].begin(),e[i].end());  //极角排序
    	for(int i=2;i<=tot;i++) {   //nxt[i]表示当前走到第i条边,下一条边走哪条
    		int v=a[i].v;
    		int t=lower_bound(e[v].begin(),e[v].end(),edge(a[i].v,a[i].u))-e[v].begin()-1;
    		if(t==-1) t=e[v].size()-1;
    		nxt[i]=e[v][t].id;
    	}
    	for(int i=2;i<=tot;i++) {
    		if(bel[i]) continue;
    		int now=nxt[i];ll s=0;bel[i]=bel[now]=++cnt;
    		s+=(p[a[now].u]-p[a[i].u])*(p[a[now].v]-p[a[i].u]);
    		while(a[now].v!=a[i].u) {
    			now=nxt[now];
    			bel[now]=cnt;s+=(p[a[now].u]-p[a[i].u])*(p[a[now].v]-p[a[i].u]);
    		}if(s<=0) rt=cnt;
    		val[cnt]=s*s; //绕着多边形转一圈,当前多边形标号为cnt
    	}
    	for(int i=1;i<=cnt;i++) f[i]=i;
    	for(int i=2;i<=tot;i+=2) {
    		int u=find(bel[i]),v=find(bel[i^1]);
    		if(u!=v) f[u]=v,T.ins(bel[i],bel[i^1]),tr[i]=tr[i^1]=1;
    	}
    	T.dfs(rt,0);
    }
    
    void solve() {
    	int k;read(k);k=(1ll*k+ans)%n+1;
    	for(int i=1;i<=k;i++) read(in[i]),in[i]=(1ll*in[i]+ans)%n+1;in[k+1]=in[1];
    	ans=0;ll res=0;
    	for(int i=1;i<=k;i++) {
    		int r=in[i],t=lower_bound(e[r].begin(),e[r].end(),edge(in[i],in[i+1]))-e[r].begin();
    		res+=(p[r]-p[in[1]])*(p[in[i+1]]-p[in[1]]);
    		int id=e[r][t].id;
    		if(!tr[id]) continue;
    		if(bel[id]==T.fa[bel[id^1]]) ans-=s2[bel[id^1]];
    		else if(T.fa[bel[id]]==bel[id^1]) ans+=s2[bel[id]];
    	}ans=abs(ans),res=abs(res);res<<=1;
    	ll t=gcd(ans,res);ans/=t,res/=t;
    	printf("%lld %lld
    ",ans,res);
    }
    
    int main() {
    	read(n),read(m),read(Q);
    	for(int i=1;i<=n;i++) read(p[i].x),read(p[i].y);
    	for(int i=1,x,y;i<=m;i++) read(x),read(y),ins(x,y),ins(y,x);
    	prepare();
    	for(int i=1;i<=Q;i++) solve();
    	return 0;
    }
    
  • 相关阅读:
    关于运行SWT程序遇到的一个错误的总结
    Window7英文系统中出现的中文乱码的更改设置
    关于SWT中的表格(TableViewer类)
    关于SWT的容器类之----面板Composite类和Group类
    关于SWT中的Combo类和List类
    js怎么获取图片的相对地址
    .NET/MVC-ViewBag、ViewData、TempData区别
    Razor语法(五)
    Razor语法(四)
    Razor语法(三)
  • 原文地址:https://www.cnblogs.com/hbyer/p/10636773.html
Copyright © 2011-2022 走看看