zoukankan      html  css  js  c++  java
  • 教主的魔法

    题目大意

    给定一个数列,支持区间加法,求区间大于等于 (c) 的数的个数

    思路

    分块裸题
    散的个体单独加,询问时单独判
    对于一整块加则打上标记
    要求块中大于等于 (c) 的数的个数
    我们不妨将块中元素排序,二分求解即可
    为了保证时间复杂度
    我们在修改的时候排序
    因为同时加一个数,相对大小不变,不需排序
    那么我们只有排暴力更改的散的个体所在的块就可以了
    时间复杂度 (O(nsqrt nlog n))

    (Code)

    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    
    const int N = 1e6 + 5;
    int n , m , a[N] , t[N] , belong[N] , st[N] , ed[N] , tag[N] , num; 
    
    inline int read()
    {
    	int res = 0;
    	char ch = getchar();
    	while (ch < '0' || ch > '9') ch = getchar();
    	while (ch >= '0' && ch <= '9') res = res * 10 + ch - '0' , ch = getchar();
    	return res;
    }
    
    inline void Sort(int x)
    {
    	for(register int i = st[x]; i <= ed[x]; i++) t[i] = a[i];
    	sort(t + st[x] , t + ed[x] + 1);
    }
    
    inline void prepare()
    {
    	num = (int)sqrt(n);
    	for(register int i = 1; i <= num; i++) st[i] = n / num * (i - 1) + 1 , ed[i] = n / num * i;
    	ed[num] = n;
    	for(register int i = 1; i <= num; i++)
    	{
    		for(register int j = st[i]; j <= ed[i]; j++) belong[j] = i;
    		Sort(i);
    	}
    }
    
    inline void change(int l , int r , int c)
    {
    	int x = belong[l] , y = belong[r];
    	if (x == y)
    	{
    		for(register int i = l; i <= r; i++) a[i] += c;
    		Sort(x);
    		return;
    	}
    	for(register int i = l; i <= ed[x]; i++) a[i] += c;
    	for(register int i = st[y]; i <= r; i++) a[i] += c;
    	for(register int i = x + 1; i <= y - 1; i++) tag[i] += c;
    	Sort(x) , Sort(y);
    }
    
    inline int query(int l , int r , int c)
    {
    	int x = belong[l] , y = belong[r] , res = 0;
    	if (x == y)
    	{
    		for(register int i = l; i <= r; i++) 
    		if (a[i] + tag[x] >= c) res++;
    		return res;
    	}
    	for(register int i = l; i <= ed[x]; i++) 
    	if (a[i] + tag[x] >= c) res++;
    	for(register int i = st[y]; i <= r; i++)
    	if (a[i] + tag[y] >= c) res++;
    	for(register int i = x + 1; i <= y - 1; i++)
    		res += ed[i] - (lower_bound(t + st[i] , t + ed[i] + 1 , c - tag[i]) - t) + 1;
    	return res;
    }
    
    int main()
    {
    	n = read() , m = read();
    	for(register int i = 1; i <= n; i++) a[i] = read();
    	prepare();
    	char opt[2];
    	int x , y , z;
    	for(register int i = 1; i <= m; i++)
    	{
    		scanf("%s" , opt);
    		x = read() , y = read() , z = read();
    		if (opt[0] == 'A') printf("%d
    " , query(x , y , z));
    		else change(x , y , z);
    	}
    }
    
  • 相关阅读:
    MySQL调优篇 | 逻辑架构解读(1)
    SQLPlus 在连接时通常有四种方式
    Oracle解决索引碎片功能
    windows2003 ftp 无法下载 解决
    bat记录
    ACCESS字符串操作函数
    缓存和RAID如何提高磁盘IO性能
    TortoiseSVN 命令 (命令行执行工具)
    在RHEL5下实现磁盘分区和磁盘配额
    PS 命令详解
  • 原文地址:https://www.cnblogs.com/leiyuanze/p/13415345.html
Copyright © 2011-2022 走看看