答案就是就是区间没有覆盖的长度
有一个直接的想法就是我们发现能够通过推倒建立起来的关系就是一个集合,也就是用并查集缩点,那么之后只需要维护一个后缀和就能做
因为我们不可以将前面的询问影响到后面的答案,因此考虑倒序做。
可以考虑维护一个栈,不断合并能够合并的点,这样后缀和就是栈顶第一个没被合并的点的后缀加上他们之间的距离
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef pair<int,int> pll; const int N=2e5+10; const int inf=0x3f3f3f3f; int p[N]; int find(int x){ if(p[x]!=x){ p[x]=find(p[x]); } return p[x]; } struct node{ int l,r; }s[N]; stack<int> q; int ql[N],qr[N]; vector<int> ans[N]; int fl[N],fr[N]; ll sum[N]; ll res[N]; int main(){ ios::sync_with_stdio(false); int n; cin>>n; int i; for(i=1;i<=n;i++){ p[i]=i; cin>>s[i].l>>s[i].r; s[i].r+=s[i].l-1; } int m; cin>>m; for(i=1;i<=m;i++){ cin>>ql[i]>>qr[i]; ans[ql[i]].push_back(i); } for(int i=n;i>=1;i--){ fl[i]=s[i].l,fr[i]=s[i].r; while(q.size()&&fr[i]>=fl[q.top()]){ int x=q.top(); q.pop(); fr[i]=max(fr[i],fr[x]); p[find(x)]=i; } if(!q.empty()){ sum[i]=sum[q.top()]+fl[q.top()]-fr[i]-1; } else sum[i]=0; q.push(i); for(int j=0;j<ans[i].size();j++){ int id=ans[i][j]; int a=qr[id]; res[id]=sum[i]-sum[find(a)]; } } for(i=1;i<=m;i++){ cout<<res[i]<<endl; } }View Code