• 【UOJ 510】某idol的人气调查


    某idol的人气调查

    暴力也有分!!!

    题目背景

    最近蔡徐坤非常烦恼 因为总是有人喜欢黑他

    于是蔡徐坤化名菜虚鲲 暗中来到 x湖一中进行人气调查

    这个学校的学生对于蔡徐坤有这样的特点

    一开始每个人的恶意值都为0

    如果一个人黑他 这个学生周围的一片人 就会累加 x点恶意值

    蔡徐坤会随机时间调查一群人的恶意值最大的那个人

    当蔡徐坤看不下去了就会给一部分人发律师函警告 这些学生的恶意值就会清零

    由于鸡你实在是太美

    请你这只鸡模拟这一过程

    题目描述 & 格式

    第一行 n表示学生数 m表示事件个数

    接下来m行

    每行3或4个数 op,L,R (v)

    若op=1 请输出区间[L,R] 的恶意最大

    若op=2 表示将区间[L,R] 恶意值清零

    若op=3 表示区间[L,R] 内的学生恶意值都加v

    提示

    初始化时修改标记要置为-1(因为会有0出现) !!切记

    这题的pushdown需要修改

    如果一个点上有区间修改标记

    那么我们只需要考虑修改标记,

    下传时把左右子节点的加法标记清零

    如果一个点上只有加法标记

    正常下传加法标记

    但是需要考虑它的左子节点和右子节点上有修改标记的情况

    如果这个节点上有修改标记,我们只需要在修改标记上+add[o]即可,不用考虑加法标记

    否则照常让加法标记 +add[o]

    这题的modify也要修改

    考虑递归到目标节点时

    如果这个节点上有修改标记,我们只需要在修改标记上+v即可,不用考虑加法标记

    否则照常让加法标记 +v

    如何写区间修改操作呢

    考虑递归到目标节点时

    将该点的最值,加法标记,修改标记全部置0即可

    对拍程序

    #include<cstdio>
    #include<iostream>
    using namespace std;
    inline int read(){
        int x;scanf("%d",&x);return x;
    } 
    int a[100000+5];
    int main(){
        int n =read(),m =read();
    //    for(int i=1;i<=n;++i)    a[i] =read();
        while(m--){
            int op =read(),l =read(),r =read();
            if(op==1){
                int ans =-999;
                for(int i=l;i<=r;++i)    ans =max(ans,a[i]);
                cout<<ans <<endl;
            }
            else if(op==2){
                for(int i=l;i<=r;++i)    a[i] =0;
            }
            else if(op==3){
                int x =read();
                for(int i=l;i<=r;++i)    a[i] +=x;
            }
        }
    }

    随机数据生成器

    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    #include<ctime>
    using namespace std;
    int main(){
        freopen("cxk.in","w",stdout);
        int n,m;
        n = m =1e3;     //此处填写数据范围 
        srand(time(0));
        cout<<n<<' '<<m<<endl;
        for(int i=1;i<=m;++i){
            int op =rand()%3+1;
            int l =rand()%n+1,r =rand()%n+1;
            if(l>r)    swap(l,r);
            cout<<op<<' '<<l<<' '<<r<<' ';
            if(op==3){
                cout<<rand()%10<<endl;
            }
            else puts("");
        }
    }

    样例

    5 4
    3 1 4 4
    1 2 3
    2 2 2
    1 2 3

    -> 4 4 4 4 0

    -> 4 0 4 4 0

    4
    4

    数据范围

    25%的点没有2操作

    另有25%的点 n,m104

    n,m106 所有值在int以内

    题解:线段树嗯,清零用乘0就可以啦

    #include<cstdio>
    #include<iostream>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<bits/stdc++.h>
    typedef long long ll;
    using namespace std;
    const int N=100003;
    int yc,n,T,x,y;
    ll z,mod,tim[N*4],mx[N*4];
    ll a[N*4],sum[N*4],add[N*4];
    void pushup(int rt) { 
        sum[rt]=(sum[rt*2]+sum[rt*2+1]); 
        mx[rt]=max(mx[rt*2],mx[rt*2+1]);
    }
    
    void build(int l,int r,int rt){
        tim[rt]=1;
        add[rt]=0;
        if(l==r){
            mx[rt]=a[l];
            return ;
        }
        int m=(l+r)/2;
        build(l,m,rt*2);
        build(m+1,r,rt*2+1);
        pushup(rt);
    }
    
    void pushdown(int rt,int ln,int rn){
        
        if(add[rt]==0 && tim[rt]==1) return;
        if(ln+rn==1) return ;
        
        mx[rt*2]=(mx[rt*2]*tim[rt]+add[rt]);
        mx[rt*2+1]=(mx[rt*2+1]*tim[rt]+add[rt]);
            
        add[rt*2]=(add[rt*2]*tim[rt]+add[rt]);
        add[rt*2+1]=(add[rt*2+1]*tim[rt]+add[rt]);
            
        add[rt]=0;
        
        tim[rt*2]=(tim[rt*2]*tim[rt]);
        tim[rt*2+1]=(tim[rt*2+1]*tim[rt]);
    
        tim[rt]=1;
    }
    
    void update1(int L,int R,ll c,int l,int r,int rt){//清零 
        int m=(l+r)/2;
        pushdown(rt,m-l+1,r-m);
        if(L<=l && r<=R) {
            mx[rt]=(mx[rt]*c);
            tim[rt]*=c;
            mx[rt]*=c;
            return ;
        }
        if(L<=m) update1(L,R,c,l,m,rt*2);
        if(R>m) update1(L,R,c,m+1,r,rt*2+1);
        pushup(rt);
    }
    
    
    void update2(int L,int R,ll c,int l,int r,int rt){//加值 
        int m=(l+r)/2;
        pushdown(rt,m-l+1,r-m);
        if(L<=l && r<=R) {
            add[rt]+=c;
            mx[rt]+=c;
            return ;
        }
        if(L<=m) update2(L,R,c,l,m,rt*2);
        if(R>m) update2(L,R,c,m+1,r,rt*2+1);
        pushup(rt);
    }
    
    ll query(int L,int R,int l,int r,int rt){
        
        if(L<=l && r<=R) return mx[rt];
        int m=(l+r)/2;
        pushdown(rt,m-l+1,r-m);
        ll ans=-1;
        if(L<=m) ans=max(ans,query(L,R,l,m,rt*2));
        if(R>m) ans=max(ans,query(L,R,m+1,r,rt*2+1));
        return ans;
    }
    
    int main(){
        
        scanf("%d %d",&n,&T);
        for(int i=1;i<=4*n;i++) tim[i]=1;
        for(int i=1;i<=n;i++) a[i]=0;
        build(1,n,1);
        while(T--){
            scanf("%d",&yc);
            if(yc==2){
                scanf("%d %d ",&x,&y);
                update1(x,y,0,1,n,1);
            }
            if(yc==3){
                scanf("%d %d %lld",&x,&y,&z);
                update2(x,y,z,1,n,1);
            }
            if(yc==1){
                scanf("%d %d",&x,&y);
                cout<<query(x,y,1,n,1)<<endl;
            }
        }
        return 0;
    }
  • 相关阅读:
    PHP 进制汉字转化
    当调用方法没有注释信息并且参数不全
    DBCP数据库连接池技术的两种实现方式
    汇编语言中一步执行循环
    求最小函数依赖集
    汇编语言实验四
    汇编语言第七章
    batch实现数据库的批量插入Unknown system variable 'query_cache_size'
    汇编语言第一节课:数制转换,真值和补码
    Forsaken喜欢数论
  • 原文地址:https://www.cnblogs.com/wuhu-JJJ/p/14030049.html
Copyright © 2020-2023  润新知