题解:
这道题的重边让我调了一下午。。
先将此平面图转化为对偶图。
注意到对偶图的dfs树的任意子树对应原图一个联通块,而此题目相当于给你把树割下若干段求和。 那么每条边暴力判断是往子树还是往父亲从而统计答案。
#include <bits/stdc++.h>
#include <tr1/unordered_map>
typedef long long LL;
using namespace std;
inline LL rd() {
char ch=getchar(); LL i=0,f=1;
while(!isdigit(ch)) {if(ch=='-')f=-1; ch=getchar();}
while(isdigit(ch)) {i=(i<<1)+(i<<3)+ch-'0'; ch=getchar();}
return i*f;
}
const int N=5e5+50,M=2e6+50;
tr1::unordered_map <int,int> S[N],S2[N];
vector < pair<double,int> > edge[N];
int n,m,q,xc[N],yc[N],g[N],nt[M],vt[M],nxt[M],ww[M],ec=1;
inline void add(int x,int y) {
if(S[x][y]) return;
nt[++ec]=g[x]; g[x]=ec; vt[ec]=y;
S[x][y]=ec;
edge[x].push_back(make_pair(atan2(yc[y]-yc[x],xc[y]-xc[x]),ec));
}
int vis[M],cnt,rt,stk[M],bl[M],top;
LL s[M],s2[M];
int g2[M],nt2[M],vt2[M],fm[M],ec2=1,istr[M];
inline void add2(int x,int y,int id) {
if(S2[x][y]) return;
nt2[++ec2]=g2[x]; g2[x]=ec2; vt2[ec2]=y;
S2[x][y]=1; ww[id]=ec2; fm[ec2]=x;
}
int dep[M];
inline void dfs(int x) {
vis[x]=1;
for(int e=g2[x];e;e=nt2[e]) {
if(vis[vt2[e]]) continue;
dep[vt2[e]]=dep[x]+1;
dfs(vt2[e]); istr[e]=1; istr[e^1]=-1;
s[x]+=s[vt2[e]]; s2[x]+=s2[vt2[e]];
}
}
inline LL cross(int x,int y) {return (LL)xc[x]*yc[y]-(LL)yc[x]*xc[y];}
inline LL gcd(LL a,LL b) {return b?gcd(b,a%b):a;}
int main() {
n=rd(), m=rd(), q=rd();
for(int i=1;i<=n;i++) xc[i]=rd(), yc[i]=rd();
for(int i=1;i<=m;i++) {
int x=rd() ,y=rd();
if(x!=y) add(x,y),add(y,x);
}
for(int i=1;i<=n;i++) {
sort(edge[i].begin(), edge[i].end());
for(int e=1;e<edge[i].size();++e)
nxt[edge[i][e].second^1]=edge[i][e-1].second;
nxt[edge[i][0].second^1]=edge[i][edge[i].size()-1].second;
}
for(int i=2;i<=ec;i++) {
if(bl[i]) continue;
stk[top=1]=i;
while(stk[1]!=nxt[stk[top]])
stk[top+1]=nxt[stk[top]], top++;
LL c=cross(vt[stk[top]],vt[stk[1]]);
for(int j=1;j<top;j++) c+=cross(vt[stk[j]],vt[stk[j+1]]);
++cnt;
if(c>0) s[cnt]=c<<1,s2[cnt]=c*c;
else rt=cnt;
for(int j=1;j<=top;j++) bl[stk[j]]=cnt;
}
for(int i=2;i<=ec;i++) add2(bl[i],bl[i^1],i);
dfs(rt);
LL lst=0;
for(int i=1;i<=q;i++) {
int d=(rd()+lst)%n+1;
for(int j=1;j<=d;j++) stk[j]=(rd()+lst)%n+1;
stk[d+1]=stk[1];
LL c=0, c2=0;
for(int j=1;j<=d;j++) {
if(!S[stk[j]].count(stk[j+1])) continue;
int id=S[stk[j]][stk[j+1]];
id=ww[id];
if(!istr[id]) continue;
int x=(istr[id]>0)?vt2[id]:fm[id];
c+=istr[id]*s[x];
c2+=istr[id]*s2[x];
}
c2=abs(c2); c=abs(c); LL t=gcd(c,c2);
c2/=t; c/=t; lst=c2;
printf("%lld %lld\n",c2,c);
}
}