"HNOI2016" mine

https://loj.ac/problem/2052

answer

Dual plan view of FIG turn. .

First, we need to turn, then all of the plane labels, and then see if they find each edge which separates the two planes.

Approach is maintained for each point it's all sorted out side, and then find a successor to its edge for each side and orderly.

If you have been looking down, you will find a plane, followed by numbers just fine.

We turned for the better dual graph, \ (the DFS \) the dual graph of a spanning tree, and then ask for one, it is definitely cut out some of the Unicom block tree.

So we talk about the direction of each edge count answer enough.

Code

#include<bits/stdc++.h>
#define N 200009
#define M 1200009
using namespace std;
typedef long long ll;
const double eps=1e-9;
int tot=1,n,m,q,pos[M],rt,b[N],nxt[M],num;
ll s[M],S[M],f[M];
bool ms[M],vis[M];
inline ll rd(){
  ll x=0;char c=getchar();bool f=0;
  while(!isdigit(c)){if(c=='-')f=1;c=getchar();}
  while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();};
  return f?-x:x;
}
struct point{
  ll x,y;
  inline point operator +(const point &b)const{return point{x+b.x,y+b.y};}
  inline point operator -(const point &b)const{return point{x-b.x,y-b.y};}
  inline ll operator *(const point &b)const{return x*b.y-y*b.x;}
}a[N];
struct edge{
  int id,u,v;
  double ang;
  inline bool operator <(const edge &b)const{
      if(fabs(ang-b.ang)>eps)return ang<b.ang;
  }
}e[M];
vector<edge>vec[N];
vector<int>ed[M],ps[M];
inline void add(int x,int y){
  ++tot;e[tot]=edge{tot,x,y,atan2(a[y].y-a[x].y,a[y].x-a[x].x)};
  vec[x].push_back(e[tot]);
}
inline void build(){
    for(int i=1;i<=n;++i)sort(vec[i].begin(),vec[i].end());
    for(int i=2;i<=tot;++i){
      int id=e[i].v;
      vector<edge>::iterator it=lower_bound(vec[id].begin(),vec[id].end(),e[i^1]);
      if(it==vec[id].begin())it=vec[id].end();
      --it;nxt[i]=it->id;
    }
    for(int i=2;i<=tot;++i)if(!pos[i]){
      pos[i]=pos[nxt[i]]=++num;
      int x=nxt[i];
      while(1){ 
        if(e[x].v==e[i].u)break;
        s[num]+=(a[e[x].u]-a[e[i].u])*(a[e[x].v]-a[e[i].u]);
        x=nxt[x];pos[x]=num;
      }
      if(s[num]<=0)rt=num,s[num]=0;
    }
    for(int i=2;i<=tot;++i)ed[pos[i]].push_back(pos[i^1]),ps[pos[i]].push_back(i);
}
void dfs(int u,int fa){
    f[u]=fa;
    S[u]=s[u]*s[u];s[u]<<=1;vis[u]=1;
    for(int i=0;i<ed[u].size();++i){
      int v=ed[u][i],tg=ps[u][i];
      if(vis[v])continue;
      ms[tg]=ms[tg^1]=1;
      dfs(v,u);
      S[u]+=S[v];s[u]+=s[v];
    }
}
ll gcd(ll x,ll y){return y?gcd(y,x%y):x;}
void solve(){
  ll ans1=0,ans2=0;
  while(q--){
    int x=(rd()+ans1)%n+1;
    for(int i=1;i<=x;++i)b[i]=(rd()+ans1)%n+1;
    ans1=ans2=0;
    b[x+1]=b[1];
    for(int i=1;i<=x;++i){
        int xx=b[i],yy=b[i+1];
     //   cout<<xx<<" "<<ans1<<" "<<ans2<<"   ";
        edge z=edge{0,xx,yy,atan2(a[yy].y-a[xx].y,a[yy].x-a[xx].x)};
        vector<edge>::iterator it=lower_bound(vec[xx].begin(),vec[xx].end(),z);
        int j=it->id;
        if(!ms[j])continue;
        if(f[pos[j]]==pos[j^1])ans1+=S[pos[j]],ans2+=s[pos[j]];
        else ans1-=S[pos[j^1]],ans2-=s[pos[j^1]];
    }
    ll g=gcd(ans1,ans2);
    ans1/=g;ans2/=g;
    printf("%lld %lld\n",ans1,ans2);
  }
}
int main(){
  n=rd();m=rd();q=rd();
  int x,y;
  for(int i=1;i<=n;++i){
      x=rd();y=rd();
      a[i]=point{x,y};
  }
  for(int i=1;i<=m;++i){
      x=rd();y=rd();
      add(x,y);add(y,x);
  }
  build();dfs(rt,0);solve();
  return 0;
}

Guess you like

Origin www.cnblogs.com/ZH-comld/p/10959532.html