很有趣的一道题 只有奇圈意味着只有单圈 然后dfs求出单圈 p[x]=y表示[x,y]ok 然后二分求解
1 #include<cstdio> 2 #include<cstring> 3 #include<cmath> 4 #include<ctime> 5 #include<iostream> 6 #include<algorithm> 7 #include<queue> 8 #include<stack> 9 #include<set> 10 #define esp (1e-6) 11 #define inf (0x3f3f3f3f) 12 #define l(a) ((a)<<1) 13 #define r(a) ((a)<<1|1) 14 #define b(a) (1<<(a)) 15 #define rep(i,a,b) for(int i=a;i<=(b);i++) 16 #define clr(a) memset(a,0,sizeof(a)) 17 typedef long long ll; 18 typedef unsigned long long ull; 19 using namespace std; 20 int readint(){ 21 int t=0,f=1;char c=getchar(); 22 while(!isdigit(c)){ 23 if(c=='-') f=-1; 24 c=getchar(); 25 } 26 while(isdigit(c)){ 27 t=(t<<3)+(t<<1)+c-'0'; 28 c=getchar(); 29 } 30 return t*f; 31 } 32 const int maxn=300009,maxm=600009; 33 struct edge{ 34 int v; 35 edge*next; 36 }e[maxm],*pt=e,*fir[maxn]; 37 int n,m,circnt,a[maxn],d[maxn],p[maxn]; 38 ll s[maxn],sum[maxn]; 39 bool check[maxn]; 40 void mul(){ 41 rep(i,1,n+1) s[i]=ll(i)*ll(i-1)/2ll; 42 } 43 void add(int u,int v){ 44 pt->v=v;pt->next=fir[u]; 45 fir[u]=pt++; 46 } 47 void addedge(int u,int v){ 48 add(u,v);add(v,u); 49 } 50 stack<int>S; 51 void Dfs(int x,int f){ 52 S.push(x);check[x]=1; 53 for(edge*e=fir[x];e;e=e->next) if(e->v!=f&&!p[e->v]){ 54 if(check[e->v]){ 55 int t=-1,cnt=0,mx=0,mn=maxn;++circnt; 56 while(t!=e->v){ 57 t=S.top();S.pop(); 58 p[t]=circnt;a[++cnt]=t; 59 mn=min(t,mn); 60 mx=max(t,mx); 61 } 62 for(int i=cnt;i;i--) S.push(a[i]); 63 d[mn]=mx; 64 }else Dfs(e->v,x); 65 } 66 S.pop(); 67 } 68 void cal(){ 69 rep(i,1,n+1) d[i]=n+1; 70 rep(i,1,n) if(!check[i]) Dfs(i,-1); 71 for(int i=n;i;i--) d[i]=min(d[i],d[i+1]); 72 rep(i,1,n) d[i]--; 73 for(int i=n;i;i--) sum[i]=sum[i+1]+ll(d[i]); 74 //puts("");rep(i,1,n) printf("%d ",d[i]);puts(""); 75 } 76 int main(){ 77 //freopen("#input.txt","r",stdin); 78 //freopen("#output.txt","w",stdout); 79 n=readint();m=readint(); 80 mul(); 81 rep(i,1,m){ 82 int U=readint(),V=readint(); 83 addedge(U,V); 84 } 85 cal(); 86 int q=readint(); 87 while(q--){ 88 int l=readint(),r=readint(),L=l,R=r; 89 while(L<R){ 90 int mid=(L+R)>>1; 91 if(d[mid]<r) L=mid+1; 92 else R=mid; 93 } 94 ll ans=s[r-l+1]+ll(r-l+1)-ll(r)*ll(L-l)+sum[l]-sum[L]; 95 cout<<ans<<endl; 96 } 97 //fclose(stdin); 98 //fclose(stdout); 99 return 0; 100 }