傳送門node
總算會平面圖轉對偶圖了……c++
首先咱們把無向邊拆成兩條單向邊,這樣的話每條邊都屬於一個面。而後把以每個點爲起點的邊按極角排序,那麼對於一條邊\((u,v)\),咱們在全部以\(v\)爲起點的邊中找到\((v,u)\)的前綴,這條邊就是\((u,v)\)的下一條邊了。不斷重複這個過程直到找到的區域封閉爲止ui
建好對偶圖以後,咱們對於每個點,算出這個點所表明的區域的面積。對於無界域(就是外圍無限的那個面),它的面積會是一個負數。那麼咱們找到這個無界域表明的節點以後,以它爲根,求出對偶圖的一棵生成樹,並記錄一會兒樹裏的礦區面積和以及礦區面積平方和spa
而後考慮詢問,對於每一條出現的邊,若是是非樹邊就忽略,不然若是這條邊所在的面是它的反邊所在的面的兒子,咱們就加上這個子樹的貢獻。不然就減去反邊所在的面的子樹的貢獻。這個畫一畫圖應該就出來了code
//minamoto #include<bits/stdc++.h> #define R register #define ll long long #define pb push_back #define IT vector<Eg>::iterator #define inline __inline__ __attribute__((always_inline)) #define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i) #define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i) #define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v) using namespace std; char buf[1<<21],*p1=buf,*p2=buf; inline char getc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;} int read(){ R int res,f=1;R char ch; while((ch=getc())>'9'||ch<'0')(ch=='-')&&(f=-1); for(res=ch-'0';(ch=getc())>='0'&&ch<='9';res=res*10+ch-'0'); return res*f; } char sr[1<<21],z[20];int C=-1,Z=0; inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;} void print(R ll x){ if(C>1<<20)Ot();if(x<0)sr[++C]='-',x=-x; while(z[++Z]=x%10+48,x/=10); while(sr[++C]=z[Z],--Z);sr[++C]=' '; } const int N=2e5+5,M=1.2e6+5;const double eps=1e-10; inline int sgn(R double x){return x<-eps?-1:x>eps;} inline double abs(R double x){return x<-eps?-x:x;} struct node{ int x,y; inline node(){} inline node(R int xx,R int yy):x(xx),y(yy){} inline node operator +(const node &b)const{return node(x+b.x,y+b.y);} inline node operator -(const node &b)const{return node(x-b.x,y-b.y);} inline ll operator *(const node &b)const{return 1ll*x*b.y-1ll*y*b.x;} }p[N]; struct Eg{ int id,u,v;double ang; inline Eg(){} inline Eg(R int ii,R int uu,R int vv,R double aa=0){id=ii,u=uu,v=vv,ang=aa;} inline bool operator <(const Eg &b)const{return sgn(ang-b.ang)?ang<b.ang:v<b.v;} }e[M];vector<Eg>h[N],tr[M];int tot=1,cnt,rt;IT it; int nxt[M],pos[M],fa[M],vis[M],is[M],st[M];ll s[M],ss[M],ans1,ans2; int n,q,m,top; void add(R int u,R int v){ ++tot,e[tot]=Eg(tot,u,v,atan2(p[v].y-p[u].y,p[v].x-p[u].x)); h[u].pb(e[tot]); } void build(){ fp(i,1,n)sort(h[i].begin(),h[i].end()); for(R int i=2,v=e[i].v;i<=tot;++i,v=e[i].v){ 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(R int i=2;i<=tot;++i)if(!pos[i]){ pos[i]=pos[nxt[i]]=++cnt; for(R int j=nxt[i],u=e[j].u,v=e[j].v;v!=e[i].u;j=nxt[j],pos[j]=cnt,u=e[j].u,v=e[j].v) s[cnt]+=(p[u]-p[e[i].u])*(p[v]-p[e[i].u]); if(s[cnt]<=0)rt=cnt; } fp(i,2,tot)tr[pos[i]].pb(Eg(i,pos[i],pos[i^1])); } void dfs(int u,int lst){ fa[u]=lst,ss[u]=s[u]*s[u],s[u]<<=1,vis[u]=1; for(int i=0,sz=tr[u].size(),v;i<sz;++i){ v=tr[u][i].v;if(vis[v])continue; is[tr[u][i].id]=is[tr[u][i].id^1]=1,dfs(v,u); s[u]+=s[v],ss[u]+=ss[v]; } } int main(){ // freopen("testdata.in","r",stdin); n=read(),m=read(),q=read(); fp(i,1,n)p[i].x=read(),p[i].y=read(); for(R int i=1,u,v;i<=m;++i)u=read(),v=read(),add(u,v),add(v,u); build(),dfs(rt,0); int u,v,w;Eg ee;ll g; while(q--){ top=(read()+ans1)%n+1; fp(i,1,top)st[i]=(read()+ans1)%n+1; st[top+1]=st[1],ans1=ans2=0; fp(i,1,top){ u=st[i],v=st[i+1]; ee=Eg(0,u,v,atan2(p[v].y-p[u].y,p[v].x-p[u].x)); it=lower_bound(h[u].begin(),h[u].end(),ee); w=it->id; if(!is[w])continue; fa[pos[w]]==pos[w^1]?(ans1+=ss[pos[w]],ans2+=s[pos[w]]):(ans1-=ss[pos[w^1]],ans2-=s[pos[w^1]]); } g=__gcd(ans1,ans2),ans1/=g,ans2/=g; print(ans1),print(ans2),sr[C]='\n'; } return Ot(),0; }