CF799F Beautiful fountains rows
这个正解比乱搞逊多了
先考虑只枚举 \(a\)。
令 \((x,y)\) 表示 \(x\) 到 \(y\) 都有喷泉的花园且如果在 \([a,x]\) 段上有非零偶数个喷泉,那么对于 \(a\) 来说 \(x\) 是禁止的。
然后考虑将所有花园分为两类:
-
\(x<a\le y\)
-
\(a\le x\le y\)
考虑第一类花园中的哪些位置是禁止的:
令 \(\mathbb R\) 为第一类花园的右端点集合,这些花园禁止位置 \(a+1,a+3,\cdots,x\)。且若 \(\mathbb R\) 中存在一个 \(t\) 满足 \(t-a+1\) 是偶数,那么位置 \(t,t+1,t+2,\cdots ,m\) 也将被禁止。显然只需要知道最小的 \(t\) 满足 \(t-a+1\) 是偶数就行了。
然后考虑第二类花园中的哪些位置是禁止的:
\(x+1,x+3,\cdots\)。且若 \(y-x+1\) 为偶数,则 \(y,y+1,y+2,\cdots\) 这些位置也都是禁止的。
可以发现哪些位置被禁止与 \(a\) 无关,因此可以预处理一个数组来求出有哪些 \(b\) 是禁止的。
然后考虑直接拿线段树维护上面那一堆东西,具体可以看代码..
时间复杂度 \(\mathcal O(n\log (n+m))\),比乱搞慢好几倍而且难写。
#include<bits/stdc++.h>
#define R(i,a,b) for(int i=(a),i##E=(b);i<=i##E;i++)
#define L(i,a,b) for(int i=(b),i##E=(a);i>=i##E;i--)
using namespace std;
typedef long long ll;
ll ans;
int n,m;
int a[222222],l[222222],r[222222];
struct sgt
{
struct node
{
int mn,cnt;
ll val;
inline node (int M=0,int C=0,ll V=0):mn(M),cnt(C),val(V) {}
inline node operator +(const node &A)const
{
if(mn<A.mn) return *this;
if(mn>A.mn) return A;
return node(mn,cnt+A.cnt,val+A.val);
}
}t[888888];
int lz[888888];
inline void push_add(int x,int k)
{
t[x].mn+=k,lz[x]+=k;
}
inline void push_down(int x)
{
push_add(x<<1,lz[x]),push_add(x<<1|1,lz[x]);
lz[x]=0;
}
void build(int opt,int l,int r,int x)
{
lz[x]=0;
if(l==r)
{
t[x].mn=0;
if((l&1)==opt) t[x].cnt=1,t[x].val=l;
else t[x].cnt=t[x].val=0;
return;
}
int mid=(l+r)>>1;
build(opt,l,mid,x<<1);
build(opt,mid+1,r,x<<1|1);
t[x]=t[x<<1]+t[x<<1|1];
}
void modify(int L,int R,int l,int r,int x,int k)
{
if(L<=l&&r<=R) return push_add(x,k);
push_down(x);
int mid=(l+r)>>1;
if(L<=mid) modify(L,R,l,mid,x<<1,k);
if(mid<R) modify(L,R,mid+1,r,x<<1|1,k);
t[x]=t[x<<1]+t[x<<1|1];
}
node query(int L,int R,int l,int r,int x)
{
if(L<=l&&r<=R) return t[x];
push_down(x);
int mid=(l+r)>>1;
if(R<=mid) return query(L,R,l,mid,x<<1);
if(L>mid) return query(L,R,mid+1,r,x<<1|1);
return query(L,R,l,mid,x<<1)+query(L,R,mid+1,r,x<<1|1);
}
}st;
inline void solve(int fl,int fr)
{
st.build(fr,1,m,1);
vector<tuple<int,int,int> >op[222222];
R(i,1,n)
{
//a<x<y
if((fr-l[i])&1)//x+1,x+3....
{
op[1].emplace_back(l[i],r[i],1);
op[l[i]].emplace_back(l[i],r[i],-1);
}
if((r[i]-l[i])&1) //y,y+1...m
{
op[1].emplace_back(r[i]+1,m,1);
op[l[i]].emplace_back(r[i]+1,m,-1);
}
//x<a<y
if((r[i]-fl)&1)//b>y
{
op[l[i]].emplace_back(r[i]+1,m,1);
op[r[i]+1].emplace_back(r[i]+1,m,-1);
}
if((fr-fl)&1)//a+1,a+3,max{R}
{
op[l[i]].emplace_back(l[i],r[i],1);
op[r[i]+1].emplace_back(l[i],r[i],-1);
}
}
//st.print(1,m,1),printf("-----------------\n");
R(i,1,m)
{
//for(auto [l,r,k]:op[i]) printf("l:%d r:%d k:%d\n",l,r,k);
for(auto [l,r,k]:op[i]) if(l<=r)
st.modify(l,r,1,m,1,k);//st.print(1,m,1),printf("-----------------\n");
if(i%2==fl)
{
auto ret=st.query(i,m,1,m,1);
if(!ret.mn) ans+=ret.val-1ll*ret.cnt*(i-1);
}
}
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(NULL);
cin>>n>>m;
R(i,1,n) cin>>l[i]>>r[i],++a[l[i]],--a[r[i]+1];
R(i,1,m) a[i]+=a[i-1];
solve(0,0),solve(0,1),solve(1,0),solve(1,1);
for(int i=1,j=1;i<=m;i=j+1,++j) if(!a[i])
{
for(;j+1<=m&&!a[j+1];++j);
int t=j-i+1;
R(k,1,t) ans-=1ll*k*(t-k+1);
}
cout<<ans<<endl;
}

浙公网安备 33010602011771号