zoukankan      html  css  js  c++  java
  • CF1404C Fixed Point Removal 题解

    题面

    初看题有点不好下手。

    考虑把数字变成 (i-a_i),这样操作就变成了删掉一个 (0)、之后的数 (-1)

    显然如果一个数 (<0) 那么它一定不能被删除,可以直接忽略。

    可以发现一个数可以被删掉,当且仅当它前面能被删掉的数的个数 (le i-a_i)。因为先删后面不会影响前面。

    考虑把询问离线,按右端点排序,从左到右扫过去。维护一个序列 ({f_i}) 表示 (isim) 结尾能删多少个数。由定义可知 (f) 序列是单调不升的。于是可以二分一个最大的 (f_j) 满足 (f_jge i-a_i),把 ([1,j])(f) 全部 (+1)。直接二分 + 树状数组做。

    #include <bits/stdc++.h>
    #define DC int T = gi <int> (); while (T--)
    #define DEBUG fprintf(stderr, "Passing [%s] line %d
    ", __FUNCTION__, __LINE__)
    #define File(x) freopen(x".in","r",stdin); freopen(x".out","w",stdout)
    #define fi first
    #define se second
    #define pb push_back
    #define mp make_pair
    
    using namespace std;
    
    typedef long long LL;
    typedef unsigned long long ULL;
    typedef pair <int, int> PII;
    typedef pair <LL, int> PLI;
    typedef pair <LL, LL> PLL;
    
    template <typename T>
    inline T gi()
    {
    	T x = 0, f = 1; char c = getchar();
    	while (c < '0' || c > '9') {if (c == '-') f = -1; c = getchar();}
    	while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
    	return f * x;
    }
    
    template <typename T> inline T abs(T x) {return x < 0 ? -x : x;}
    
    const int N = 300003, M = N << 1;
    
    int n, q, a[N];
    struct Query {int l, r, id;} b[N];
    vector <Query> l[N];
    int ans[N];
    
    struct BIT
    {
    	int tr[N];
    #define lowbit(i) (i & (-i))
    	void add(int u, int x) {for (int i = u; i <= n; i += lowbit(i)) tr[i] += x;}
    	int query(int x) {int res = 0; for (int i = x; i; i -= lowbit(i)) res += tr[i]; return res;}
    	int query(int l, int r) {return query(r) - query(l - 1);}
    } t;
    
    int main()
    {
    	n = gi <int> (), q = gi <int> ();
    	for (int i = 1; i <= n; i+=1) a[i] = gi <int> ();
    	for (int i = 1; i <= q; i+=1) b[i].id = i, b[i].l = gi <int> () + 1, b[i].r = n - gi <int> (), l[b[i].r].pb(b[i]);
    	for (int i = 1; i <= n; i+=1)
    	{
    		if (a[i] <= i)
    		{
    			int l = 1, r = i, res = -1;
    			while (l <= r)
    			{
    				int mid = (l + r) >> 1;
    				if (t.query(mid) >= i - a[i]) res = mid, l = mid + 1;
    				else r = mid - 1;
    			}
    			if (res != -1) t.add(1, 1), t.add(res + 1, -1);
    		}
    		for (auto x : l[i]) ans[x.id] = t.query(x.l);
    	}
    	for (int i = 1; i <= q; i+=1) printf("%d
    ", ans[i]);
    	return 0;
    }
    
  • 相关阅读:
    js 与 asp.net 验证控件冲突解决方法
    图片处理(给图片加水印)
    JS打开窗口
    ASP.NET编程中的十大技巧
    【ASP.NET】FCKeditor 2.6 + Asp.Net 设置
    XML文件设置树形结构(无限级)原创
    利用vs.net快速开发windows服务(c#) (转载)
    C#反射 学习
    C#解压RAR压缩文件(转载测试通过)
    SQL显示字段信息
  • 原文地址:https://www.cnblogs.com/xsl19/p/cf1404c.html
Copyright © 2011-2022 走看看