Naive Operations HDU6315 (杭电多校2G)

让ci = ai / bi, 求sum(ci)的值,因为每次 ai 都是加一的,那么我可以用一颗线段树来维护每个 i 位置的 ai 距离达到 bi 还需要的数的最小值,更新是每次都减一,如果我某一个区间的最小值等于 0, 这就说明我这时候的ai已经满足了ai/bi==1的情况,那么对应的ci的位置就应该加一,所以我每次发现一个区间的最小值是0的话,我就 dfs 去找到为0的地方,把这里重新修改成bi,然后这个位置的答案+1就可以了

#include<map>
#include<set>
#include<ctime>
#include<cmath>
#include<stack>
#include<queue>
#include<string>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define first fi
#define second se
#define lowbit(x) (x & (-x))

typedef unsigned long long int ull;
typedef long long int ll;
const double pi = 4.0*atan(1.0);
const int inf = 0x3f3f3f3f;
const int maxn = 100005;
const int maxm = 100000;
const int mod = 998244353;
using namespace std;

int n, m, tol, T;
int a[maxn];
int b[maxn];
int c[maxn << 2];
int sum[maxn << 2];
int lazy[maxn << 2];

void init() {
    memset(a, 0, sizeof a);
    memset(b, 0, sizeof b);
    memset(c, 0, sizeof c);
    memset(sum, inf, sizeof sum);
    memset(lazy, 0, sizeof lazy);
}

void pushup(int root) {
    sum[root] = min(sum[root << 1], sum[root << 1 | 1]);
    c[root] = c[root << 1] + c[root << 1 | 1];
}

void pushdown(int root) {
    if(lazy[root] != 0) {
        lazy[root << 1] += lazy[root];
        lazy[root << 1 | 1] += lazy[root];
        sum[root << 1] -= lazy[root];
        sum[root << 1 | 1] -= lazy[root];
        lazy[root] = 0;
    }
    return ;
}

void build(int left, int right, int root) {
    if(left == right) {
        sum[root] = b[left];
        return ;
    }
    int mid = (left + right) >> 1;
    build(left, mid, root << 1);
    build(mid+1, right, root << 1 | 1);
    pushup(root);
}

void dfs(int left, int right, int root) {
    if(left == right) {
        if(sum[root] == 0) {
            sum[root] = b[left];
            c[root]++;
        }
        return ;
    }
    pushdown(root);
    int mid = (left + right) >> 1;
    if(sum[root << 1] == 0)
        dfs(left, mid, root << 1);
    if(sum[root << 1 | 1] == 0)
        dfs(mid+1, right, root << 1 | 1);
    pushup(root);
}

void update(int left, int right, int prel, int prer, int root) {
    if(prel <= left && right <= prer) {
        lazy[root]++;
        sum[root]--;
        while(sum[root] == 0)    dfs(left, right, root);
        return ;
    }
    pushdown(root);
    int mid = (left + right) >> 1;
    if(prel <= mid)    update(left, mid, prel, prer, root << 1);
    if(prer > mid)    update(mid+1, right, prel, prer, root << 1 | 1);
    pushup(root);
}

int query(int left, int right, int prel, int prer, int root) {
    if(prel <= left && right <= prer) return c[root];
    int mid = (left + right) >> 1;
    int ans = 0;
    if(prel <= mid)    ans += query(left, mid, prel, prer, root << 1);
    if(prer > mid)    ans += query(mid+1, right, prel, prer, root << 1 | 1);
    return ans;
}

int main() {
    while(~scanf("%d%d", &n, &m)) {
        init();
        for(int i=1; i<=n; i++)    scanf("%d", &b[i]);
        build(1, n, 1);
        char str[15];
        while(m--) {
            int l, r;
            scanf("%s%d%d", str, &l, &r);
            if(str[0] == ‘a‘) {
                update(1, n, l, r, 1);
            } else if(str[0] == ‘q‘) {
                int ans = query(1, n, l, r, 1);
                printf("%d\n", ans);
            }
        }
    }
    return 0;
}

原文地址:https://www.cnblogs.com/H-Riven/p/9371067.html

时间: 2024-10-10 07:01:20

Naive Operations HDU6315 (杭电多校2G)的相关文章

HDU 4975 (杭电多校 #10 1005题)A simple Gaussian elimination problem.(网络流之最大流)

题目地址:HDU 4975 对这题简直无语...本来以为这题要用什么更先进的方法,结果还是老方法,这么卡时间真的好吗....比赛的时候用了判环的方法,一直TLE..后来换了矩阵DP的方式,加了加剪枝就过了..无语了.. 代码如下: #include <cstdio> #include <cstring> #include <algorithm> #include <iostream> #include <cstdio> #include <

HDU 4937 (杭电多校 #7 1003题)Lucky Number(瞎搞)

题目地址:HDU 4937 多校的题以后得重视起来...每道题都错好多次...很考察细节.比如这道....WA了无数次.... 这题的思路自己真心想不到...这题是将进制后的数分别是1位,2位,3位和更多位的分开来计算. 当是1位的时候,显然只有3到6,此时只能是-1 当是2位的时候,可以转换成一元一次方程求解 当是3位的时候,可以转换成一元二次方程求解 当是4位的时候,此时最多也只有7000个数,7000^3接近1e12.所以剩下的直接枚举进制数来判断即可. 代码如下: #include <i

HDU 4888 (杭电多校#3)Redraw Beautiful Drawings(网络流之最大流)

题目地址:HDU 4888 自己之所以弱真心是态度的问题,以后不能再偷懒了!!那次这个题一直没补,结果这次又遇到了..还有这次遇到的最小割权闭合问题,也一直没刷,所以这次遇到了也不会,连是最小割都不知道!!(突然想起来前面还有好多题拖到现在也没做...T U T)以后绝不能再拖拉了! 这题的建图是很容易的,主要是判断唯一性不好判断.这里是用的dfs找环来判断是否唯一,因为假如有环的话,说明环 中的数字是可以相互流动而且可以保证解依然正确.. 代码如下: #include <cstdio> #i

HDU 5742 It&#39;s All In The Mind (贪心) 2016杭电多校联合第二场

题目:传送门. 题意:求题目中的公式的最大值,且满足题目中的三个条件. 题解:前两个数越大越好. #include <iostream> #include <algorithm> #include <cstdio> #include <cstring> using namespace std; int gcd(int a,int b) { if(!b) return a; return gcd(b,a%b); } int main() { int t; ci

HDU 4940(杭电多校#7 1006) Destroy Transportation system(瞎搞)

题目地址:HDU 4940 当时这个题一看就看出来了是网络流的最小割,然后就一直在想建图..然后突然发现,应该要让T集合的数目最少,不然只要有两个,那这两个的每一个都可以跑到S集合,使得T集合变小.那就只能是1个了.然后..枚举就好了..但是虽然觉得这么做肯定没错..但是不敢敲..因为当时都3个小时了才只有10个队过了...后来又想了几遍后觉得这样没错,就写完交上了.果然AC... 代码如下: #include <iostream> #include <cstdio> #inclu

HDU 4901(杭电多校训练#3 1005题)The Romantic Hero(DP)

题目地址:HDU 4901 这题没想到最后居然能够做出来.... 这题用了两次DP,先从前往后求一次异或的,再从后往前求一次与运算的.分别是 1:求异或的时候,定义二维数组huo[1000][1024],前者指第几位,后者是哈希的思想,若huo[x][y]=2则表示最右边的数为第x位时,异或值为y的出现了两次,需要再定义一个hash数组,来保存前面出现的所有情况,再找有多少位的时候,用hash数组中出现的所有的值与当前的第x位的数字进行异或. 2:求与的时候,定义二维数组yu[1000][102

HDU 4970(杭电多校#9 1011题)Killing Monsters(瞎搞)

题目地址:HDU 4970 先进行预处理,在每个炮塔的火力范围边界标记一个点.然后对每个点的伤害值扫一遍就能算出来.然后在算出每个点到终点的总伤害值,并保存下来,也是扫一遍即可.最后在询问的时候直接判断即可,复杂度O(2*n). 代码如下: #include <cstdio> #include <cstring> #include <algorithm> using namespace std; #define maxn 110000 #define LL __int6

HDU 4923 (杭电多校 #6 1003题)Room and Moor(公式+栈)

题目地址:HDU 4923 比赛的时候脑残了..思路完全想出来了..只不过想出了个根本不可能存在的极端数据,然后一看输入数据是100组,就把自己给否决了...sad..当时就应该大胆试一试的... 这个题首先可以把最前面的0和最后面的1去掉,因为这两块总可以用0和1抵消掉.然后中间就分成了10相间的情况,然后根据10相间,可以分成若干组,每一组都是由几个1和几个0组成的.比如说1101101110,就可以分成110,110,1110这样的三组. 然后这时候可以可以对每一组内只取一个数来使得这组的

HDU 4961(杭电多校#9 1002题)Boring Sum(瞎搞)

题目地址:HDU 4961 看来这题的测试数据是随机的.不然出了极限数据还真过不了...这题我的方法是建一个哈希结构体,记录两个变量,分别是num位置,然后是f,f==0表示这个数没出现过,f==1表示这个数出现过.然后分别从前面和后面扫一遍.每次扫的时候,对每一个出现的数都进行标记.然后对当前的数枚举该数的倍数,全部枚举完,取位置num最大的.然后找完之后,对哈希结构体进行更新.如果前面曾经出现过的话,就直接换掉,因为后面的数总比前面的更优.最后扫完两遍之后两个数组就能求出来了.计算就行了.