HDU-DuoXiao第二场hdu 6315 Naive Operations 线段树

hdu 6315

题意:对于一个数列a,初始为0,每个a[ i ]对应一个b[i],只有在这个数字上加了b[i]次后,a[i]才会+1。

    有q次操作,一种是个区间加1,一种是查询a的区间和。

思路:线段树,一开始没用lazy,TLE了,然后开始想lazy的标记,这棵线段树的特点是,每个节点维护 :一个区间某个a 要增加1所需个数的最小值,一个区间已加上的mx的最大值标记,还有就是区间和sum。 (自己一开始没有想到mx标记,一度想把lazy传回去。

(思路差一点就多开节点标记。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <string>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <list>
#include <cstdlib>
#include <iterator>
#include <cmath>
#include <iomanip>
#include <bitset>
#include <cctype>
#include <stack>
#pragma comment(linker, "/STACK:102400000,102400000")  //c++
using namespace std;

#define lson (l , mid , rt << 1)
#define rson (mid + 1 , r , rt << 1 | 1)
#define debug(x) cerr << #x << " = " << x << "\n";
#define pb push_back
#define pq priority_queue

typedef long long ll;
typedef unsigned long long ull;

typedef pair<ll ,ll > pll;
typedef pair<int ,int > pii;

#define fi first
#define se second

#define OKC ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define FT(A,B,C) for(int A=B;A <= C;++A)  //用来压行
#define REP(i , j , k)  for(int i = j ; i <  k ; ++i)

const ll mos = 0x7FFFFFFF;  //2147483647
const ll nmos = 0x80000000;  //-2147483648
const int inf  = 0x3f3f3f3f;
template<typename T>
inline T read(T&x){
    x=0;int f=0;char ch=getchar();
    while (ch<‘0‘||ch>‘9‘) f|=(ch==‘-‘),ch=getchar();
    while (ch>=‘0‘&&ch<=‘9‘) x=x*10+ch-‘0‘,ch=getchar();
    return x=f?-x:x;
}
// #define _DEBUG;         //*//
#ifdef _DEBUG
freopen("input", "r", stdin);
// freopen("output.txt", "w", stdout);
#endif
/*----------------------show time----------------------*/
int n,q;
const int maxn = 100009;
int a[maxn],b[maxn];
int sum[maxn*4];
int lazy[maxn*4];
int mx[maxn*4];
int nd[maxn*4];

void pushup(int rt){
    sum[rt] = sum[rt<<1] + sum[rt<<1|1];
    nd[rt] = min(nd[rt<<1] , nd[rt<<1|1]);
    mx[rt] = max(mx[rt<<1], mx[rt<<1|1]);
    // lazy[rt] = lazy[rt<<1] + lazy[rt<<1|1];
    // lazy[rt<<1] = lazy[rt<<1|1] = 0;
}

    void pushdown(int rt){
        if(lazy[rt]){
            lazy[rt<<1]+= lazy[rt];
            lazy[rt<<1|1] += lazy[rt];
            mx[rt<<1] +=lazy[rt];
            mx[rt<<1|1] +=lazy[rt];
            lazy[rt] = 0;
        }
    }
    void build(int l,int r,int rt){
        if(l==r){
            nd[rt] = b[l];
            lazy[rt] = mx[rt] = sum[rt] = 0;
            return;
        }
        int mid = (l+r)/2;
        build(l,mid,rt<<1);
        build(mid+1,r,rt<<1|1);
        pushup(rt);
    }

    void update(int l,int r,int rt,int L,int R,int k){
            if(l>=L && r<=R)
            {
                    mx[rt] ++;
                    if(mx[rt] < nd[rt]){
                        lazy[rt]++;
                        return;
                    }
                    if(l==r){
                        sum[rt]++;
                        nd[rt]+=b[l];
                        lazy[rt] = 0;
                        return;
                    }

            }
            int mid = (l+r)/2;
            pushdown(rt);
            if(mid >= L)update(l,mid,rt<<1,L,R,k);
            if(mid<R)update(mid+1,r,rt<<1|1,L,R,k);
            pushup(rt);
       }

        ll query(int l,int r,int rt,int L,int R){
                if(l>=L&&r<=R){
                    return sum[rt];
                }
                int mid = (l+r)/2;
                // pushdown(rt);
                ll ans = 0;
                if(mid >= L)ans += query(l,mid,rt<<1,L,R);
                if(mid < R)ans += query(mid+1,r,rt<<1|1,L,R);
                return ans;
        }
int main(){

        while(~scanf("%d%d", &n, &q)){

                for(int i=1; i<=n; i++){
                    scanf("%d", &b[i]);
                }
                char s[20];
                build(1,n,1);
                for(int i=1; i<=q; i++){
                    int l,r;
                    scanf("%s%d%d", s, &l, &r);
                    if(s[0]==‘a‘){
                        update(1,n,1,l,r,0);
                        // debug(a[5]);
                    }
                    else {
                        ll ans = query(1,n,1,l,r);
                        printf("%lld\n",ans);
                    }
                }
        }

    return 0;
}

HDU 6315

原文地址:https://www.cnblogs.com/ckxkexing/p/9374556.html

时间: 2024-10-07 03:51:56

HDU-DuoXiao第二场hdu 6315 Naive Operations 线段树的相关文章

HDU - 6315(2018 Multi-University Training Contest 2) Naive Operations (线段树区间操作)

http://acm.hdu.edu.cn/showproblem.php?pid=6315 题意 a数组初始全为0,b数组为1-n的一个排列.q次操作,一种操作add给a[l...r]加1,另一种操作query查询Σfloor(ai/bi)(i=l...r). 分析 真的是太naive啦,现场时没做出来. 看见区间自然想起线段树,那么这里的关键就是整除问题,只有达到一定数量才会对区间和产生影响. 反过来想,先把a[i]置为b[i],那么每次add时就是-1操作,当a[i]为0时区间和+1,再把

HDU6315 Naive Operations(线段树 复杂度分析)

题意 题目链接 Sol 这题关键是注意到题目中的\(b\)是个排列 那么最终的答案最多是\(nlogn\)(调和级数) 设\(d_i\)表示\(i\)号节点还需要加\(d_i\)次才能产生\(1\)的贡献 用线段树维护每个节点里\(d_i\)的最小值,每次当\(d_i - 1= 0\)的时候往下递归即可 时间复杂度:\(O(nlog^2 n)\) 多组数据记得清空lazy标记啊qwq.... #include<bits/stdc++.h> using namespace std; const

hdu 4893 (多校1007)Wow! Such Sequence!(线段树&amp;二分&amp;思维)

Wow! Such Sequence! Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 352    Accepted Submission(s): 104 Problem Description Recently, Doge got a funny birthday present from his new friend, Prot

hdu 5023 A Corrupt Mayor&#39;s Performance Art (线段树+区间更新+状压)

A Corrupt Mayor's Performance Art Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 100000/100000 K (Java/Others) Total Submission(s): 699    Accepted Submission(s): 267 Problem Description Corrupt governors always find ways to get dirty money.

hdu 1754  I Hate It (线段树)

链接:http://acm.hdu.edu.cn/showproblem.php?pid=1754 Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 35640    Accepted Submission(s): 14034 Problem Description 很多学校流行一种比较的习惯.老师们很喜欢询问,从某某到某某当中,分数最高的

HDU 5023 A Corrupt Mayor&#39;s Performance Art 线段树区间更新+状态压缩

Link:  http://acm.hdu.edu.cn/showproblem.php?pid=5023 1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <vector> 6 #include <string> 7 #include <cmath> 8 using namesp

题解 HDU 3698 Let the light guide us Dp + 线段树优化

http://acm.hdu.edu.cn/showproblem.php?pid=3698 Let the light guide us Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 62768/32768 K (Java/Others) Total Submission(s): 759    Accepted Submission(s): 253 Problem Description Plain of despair was

hdu 4970 killing monster 代代相传刷qq 不用线段树啦~

[题意]塔防游戏,一条n长的路上,有m个炮台,可以覆盖[li,ri]范围,威力ci,即每一秒,炮塔可以对范围 内的怪物可以造成ci点伤害.只有有q只怪物,每只怪物有hi点血,出现位置为xi:当怪物血量减少到0或以下时消失,怪物一直朝n位置前进.问有几只怪物可以离开这条路. [题解]用线段树可以做,不过还好我们有代代相传的刷qq 算法 ,让解法变得简单的多~    ^_^ 1 #include <iostream> 2 #include <cstdio> 3 #include <

hdu 5023 A Corrupt Mayor&#39;s Performance Art(线段树区间更新)

#include<stdio.h> #include<iostream> #include<string.h> #include<algorithm> using namespace std; int tree[5001000],add[5001000]; int color[50]; int n,m; void pushup(int pos) { tree[pos]=tree[pos<<1]|tree[pos<<1|1]; //更新