刚刚开始比赛的时候,发现这道题几分钟就有人a了,然后就以为是道水题,结果怒肝了一会之后才发现不对劲。本弱鸡补题的时候也是一把辛酸泪,想了半天后还是选择找了个大佬的讲解看了看,  [https://blog.csdn.net/liufengwei1/article/details/96836978]这是大佬的链接。
      理解后发现这道题其实不难,只是因为我自己思维的局限性导致的,以下是我对这道题的一个理解:
       对于刚刚拿到这道题的时候,我个人的一个想法就是将每一个全1的区间根据其中1的个数来累计出和大于0的区间个数,再与该全1区间的两边的-1进行联系,之后发现这样想这道题好像就写不出来了,因为我发现自己无法解决当多个全1区间联系起来的情况(可能只是因为我比较菜,写不出来。。所以我不敢否定其可行性),但我们回过头来思考这道题,这道题本质上应该就是一个求区间和的题目,而区间和的求法一般能想到前缀和,想到这一点后,我们再来看看之前的难点,连通的全1区间的处理,如果说将这个问题单独来看的话,其实也是好解决的,再加上之前的前缀和,因此便出现了这样的思路:先将连通区间处理好,再求每个连通区间的前缀和。那么现在最后的问题就是如何根据前缀和来求全1区间了,当我们把前缀和求出来后,不难想到,如果在区间左边的一个前缀和,在其右边有一个大于它的前缀和,那么就可以判断这两个之间的区间是一个和大于0的区间,因此我们只需要知道每一个前缀和有多少个比它大的前缀和,再记录有多少比它大的再它左边然后计算时将其剪掉即可,代码如下(第一次写博客,如果有什么说错的位置希望各位大佬指出,我会改正的,谢谢!):
 #include<bits/stdc++.h>
#define ll long long
using namespace std;
const int INF = 0x3f3f3f3f;
const int MAXN = 1e7,MAXM=1e6;
int l[MAXM+5],r[MAXM+5],f[MAXM+5]/*从左到右连续段贡献值*/,g[MAXM+5]/*从右到左连续段贡献值*/;
int sum[MAXN*3+5]/*前缀和*/,c[MAXN*3+5]/*lazy标记*/,b[MAXN*3+5]/*sum值的记录*/;
int main()
{
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d%d",&l[i],&r[i]);
    f[1]=r[1]-l[1]+1;
    for(int i=2;i<=n;i++)
    {
        f[i]=max(0,f[i-1]-(l[i]-r[i-1]-1))+r[i]-l[i]+1;
    }/*从左到右连续段贡献值,判断i区间能否与i+1区间联系*/
    g[n]=r[n]-l[n]+1;
    for(int i=n-1;i>=1;i--)
    {
        g[i]=max(0,g[i+1]-(l[i+1]-r[i]-1))+r[i]-l[i]+1;
    }/*从右到左连续段贡献值,判断i区间能否与i-1区间联系*/
    ll ans=0;
    int i=1;
    int base=10000000;
    while(i<=n)
    {
        sum[0]=0;
        int j=i+1;
        while(j=l[j]-r[j-1]-1) j++;//判断i区间与哪些区间相连
        j--;
        int left=max(0,l[i]-g[i]);
        int right=min(1000000000-1,r[j]+f[j]);
        //边界判断
        int t=i,mi=INF,mx=0/*前缀和大小的上下界*/;

        for(int k=left;k<=right;k++)
        {
            if(k>=l[t]&&k<=r[t]) sum[k-left+1]=sum[k-left]+1;
            else sum[k-left+1]=sum[k-left]-1;
            //计算前缀和
            if(k==r[t]) t++;
            mi=min(mi,sum[k-left+1]+base);
            mx=max(mx,sum[k-left+1]+base);
            b[sum[k-left+1]+base]++;
            //记录前缀和
        }

        for(int k=mx-1;k>=mi;k--) b[k]+=b[k+1];
        //这里计算后缀和,b[k+1]则表示比k大的值有多少个
        ans+=b[base+1];
        //包含最左侧点的值
        for(int k=left;k<=right;k++)
        {
            int t=sum[k-left+1]+base;
            b[t+1]-=c[t+1];//b[t+1]表示比t大的值有多少个,而c[t+1]表示在k的左边比t大的值有多少个
            c[t]+=c[t+1]+1;//lazy标记传递
            c[t+1]=0;//清零
            ans+=b[t+1];
        }

        for(int k=mi;k<=mx;k++) b[k]=0,c[k]=0;//清零
        i=j+1;
    }
    printf("%lld\n",ans);
    return 0;
}