#樹狀陣列#洛谷 5677 [GZOI2017]配對統計
阿新 • • 發佈:2020-11-03
分析
考慮處理出所有右端點的能夠匹配的左端點,然後用樹狀陣列離線查詢
程式碼
#include <cstdio> #include <cctype> #include <vector> #include <algorithm> #define rr register using namespace std; const int N=300011; vector<int>K[N]; struct rec{int w,rk;}a[N]; struct three{int l,r,rk;}q[N]; int c[N],n,m,ans[N]; long long Ans; inline signed iut(){ rr int ans=0; rr char c=getchar(); while (!isdigit(c)) c=getchar(); while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar(); return ans; } inline void update(int x,int y){ for (;x<=n;x+=-x&x) c[x]+=y; } inline signed query(int x){ rr int ans=0; for (;x;x-=-x&x) ans+=c[x]; return ans; } inline void add(int x,int y){ if (x>y) x^=y,y^=x,x^=y; K[y].push_back(x); } bool cmp1(rec x,rec y){return x.w<y.w;} bool cmp2(three x,three y){return x.r<y.r;} signed main(){ n=iut(); m=iut(); for (rr int i=1;i<=n;++i) a[i]=(rec){iut(),i}; sort(a+1,a+1+n,cmp1); for (rr int i=1;i<=n;++i){ rr int t=2e9; if (i>1&&a[i].w-a[i-1].w<t) t=a[i].w-a[i-1].w; if (i<n&&a[i+1].w-a[i].w<t) t=a[i+1].w-a[i].w; if (i>1&&a[i].w-a[i-1].w==t) add(a[i].rk,a[i-1].rk); if (i<n&&a[i+1].w-a[i].w==t) add(a[i].rk,a[i+1].rk); } for (rr int i=1;i<=m;++i) q[i]=(three){iut(),iut(),i}; sort(q+1,q+1+m,cmp2); for (rr int i=1,j=1;i<=m;++i){ for (;j<=q[i].r;++j){ rr int len=K[j].size(); for (rr int o=0;o<len;++o) update(K[j][o],1); } ans[q[i].rk]=query(q[i].r)-query(q[i].l-1); } for (rr int i=1;i<=m;++i) Ans+=1ll*ans[i]*i; return !printf("%lld",Ans); }