JZOJ 4298. 【NOIP2015模拟11.2晚】我的天
题目


思路
其实很好想
设 \(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\n" , ans - last);
last = ans;
}
}

浙公网安备 33010602011771号