题目
思路
其实很好想
设 (f_i) 表示 (i) 与编号 (f_i) 到 (i-1) 的人已经相识
(f_i) 初值为 (i)
那么转移就是 (f_i = min(f_i,l)) 其中 (l leq i leq r)
然后更新后的 (f_i) 和以前的 (f_i) 差值和即为答案
我们可以 (O(n^2)) 更新 (f)
可以拿 (50) 分
然后可以发现 (f) 数组具有单调性,适当 (break) 就行了
可以拿 (70) 分
满分做法其实已经能很容易看出
我们对 (f) 的更新相当于每次对区间取 (min)
吉司机线段树维护一下就好
维护 (f) 的和和一些套路的东西
答案其实是这次整体的 (f) 的和减去上次 (f) 的整体和
这就是新增
(Code)
#include<cstdio>
#include<iostream>
#define ls (k << 1)
#define rs (ls | 1)
using namespace std;
typedef long long LL;
const int N = 3e5 + 5;
int n , m , INF = 0x3f3f3f3f;
LL last;
struct segment{
LL sum;
int mx , se , cnt , tag;
}seg[N << 2];
inline void pushup(int k)
{
seg[k].sum = seg[ls].sum + seg[rs].sum;
seg[k].mx = max(seg[ls].mx , seg[rs].mx);
if (seg[ls].mx == seg[rs].mx)
{
seg[k].se = max(seg[ls].se , seg[rs].se);
seg[k].cnt = seg[ls].cnt + seg[rs].cnt;
}
else if (seg[ls].mx < seg[rs].mx)
{
seg[k].se = max(seg[ls].mx , seg[rs].se);
seg[k].cnt = seg[rs].cnt;
}
else {
seg[k].se = max(seg[ls].se , seg[rs].mx);
seg[k].cnt = seg[ls].cnt;
}
}
inline void build(int l , int r , int k)
{
seg[k].tag = INF;
if (l == r)
{
seg[k].mx = l , seg[k].se = -INF , seg[k].cnt = 1;
return;
}
int mid = (l + r) >> 1;
build(l , mid , ls) , build(mid + 1 , r , rs);
pushup(k);
}
inline void push_min(int k , int z)
{
if (z >= seg[k].mx) return;
seg[k].sum += 1LL * (seg[k].mx - z) * seg[k].cnt;
seg[k].mx = seg[k].tag = z;
}
inline void pushdown(int l , int r , int k)
{
int mid = (l + r) >> 1;
if (seg[k].tag)
{
push_min(ls , seg[k].tag) , push_min(rs , seg[k].tag);
seg[k].tag = INF;
}
}
inline void update(int x , int y , int z , int l , int r , int k)
{
if (z >= seg[k].mx) return;
if (x <= l && r <= y && seg[k].se < z) return push_min(k , z);
pushdown(l , r , k);
int mid = (l + r) >> 1;
if (x <= mid) update(x , y , z , l , mid , ls);
if (y > mid) update(x , y , z , mid + 1 , r , rs);
pushup(k);
}
inline LL query(int x , int y , int l , int r , int k)
{
if (x <= l && r <= y) return seg[k].sum;
pushdown(l , r , k);
LL res = 0;
int mid = (l + r) >> 1;
if (x <= mid) res += query(x , y , l , mid , ls);
if (y > mid) res += query(x , y , mid + 1 , r , rs);
return res;
}
int main()
{
freopen("ohmygod.in" , "r" , stdin);
freopen("ohmygod.out" , "w" , stdout);
scanf("%d%d" , &n , &m);
int x , y;
build(1 , n , 1);
while (m--)
{
scanf("%d%d" , &x , &y);
update(x , y , x , 1 , n , 1);
LL ans = query(1 , n , 1 , n , 1);
printf("%lld
" , ans - last);
last = ans;
}
}