A.Eddy Walker
蒙特卡洛+猜答案
注意答案要累乘
H.Second Large Rectangle
最大的可以用
R
M
Q
RMQ
RMQ做
然后挖掉四个角分别再做一次即可
J.Subarray
挂一下大佬的链接
https://www.cnblogs.com/FST-stay-night/p/11218660.html
最重要的是学会了前缀和查询相差为
1
1
1的时候的奇技淫巧
#include<iostream>
#include<cstdio>
#define fo(i,a,b) for(i=a;i<=b;i++)
#define fd(i,a,b) for(i=a;i>=b;i--)
#define N 10000005
#define left lt
#define right rt
using namespace std;
int n,i,j,limit,base,left,right,num,delta,mn,mx,t;
long long res;
int l[N/10+5],r[N/10+5],f[N],g[N],sum[N*3],b[N*3],c[N*3];
int main()
{
cin>>n;
fo(i,1,n) scanf("%d%d",&l[i],&r[i]);
f[1] = r[1] - l[1] + 1;
fo(i,2,n) f[i] = max(0,f[i-1]-(l[i]-r[i-1]-1)) + r[i] - l[i] + 1;
g[n] = r[n] - l[n] + 1;
fd(i,n-1,1) g[i] = max(0,g[i+1]-(l[i+1]-r[i]-1)) + r[i] - l[i] + 1;
i = 1; limit = 1000000000 - 1;
base = 10000000; //-1e7~1e7 base = 1e7
while (i <= n)
{
j = i;
while (j+1 <= n && f[j]+g[j+1]>=l[j+1]-r[j]-1) j++;
left = l[i] - g[i]; if (left < 0) left = 0;
right = r[j] + f[j]; if (right > limit) right = limit;
num = i; sum[0] = 0; mx = 0; mn = limit+1;
fo(i,left,right)
{
delta = i-left+1;
if (i >= l[num] && i <= r[num])
sum[delta] = sum[delta-1] + 1;
else
sum[delta] = sum[delta-1] - 1;
if (i == r[num]) num++;
mn = min(mn,sum[delta]+base);
mx = max(mx,sum[delta]+base);
b[sum[delta]+base]++;
if (sum[delta] > 0) res++;
}
fd(i,mx-1,mn) b[i] += b[i+1];
fo(i,left,right)
{
delta = i-left+1; t = sum[delta] + base;
b[t+1] -= c[t+1];
res += b[t+1];
c[t] += c[t+1] + 1;
c[t+1] = 0;
}
fo(i,mn,mx) b[i] = c[i] = 0;
i = j + 1;
}
cout<<res<<endl;
return 0;
}