• 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
    " , ans - last);
    		last = ans;
    	}
    }
    
  • 相关阅读:
    vuejs 2 生命周期钩子函数
    js 原型链
    两段代码说明 闭包,变量提升 问题
    node 模块全局位置
    git 提交代码
    mongoose 由一个版本引起的问题
    box-shadow 让div 立体起来
    flexbox 学习笔记 参考阮一峰老师的blog
    Linq的分页与组合查询的配合使用
    发送邮件和数据导出
  • 原文地址:https://www.cnblogs.com/leiyuanze/p/13434539.html
Copyright © 2020-2023  润新知