zoukankan      html  css  js  c++  java
  • POJ2886 Who Gets the Most Candies? 线段树 反素数

    题意:有一群小朋友围成一个环,编号1,2,3…N。每个人手上握着一个非0的数字,首先第K个人出列,然后看他手上的数字,假设为m,则从下一个开始第m个人出列,一直如此。并设i为小于等于N的最大反素数,问第i个出列的人得编号,i的约数个数。(设g(i)为i的约数的个数,若任意j<i,都有g(j)<g(i)则i为反素数)。

    首先要得到[0,N]的最大反素数(怎么得到下面再说),然后模拟出列操作,用线段树来优化使得每次出列在O(logN)时间内完成。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    using namespace std;
    
    #define maxn 100005
    
    int maxsub[maxn<<2], minsub[maxn<<2];
    int lmax[maxn<<2], rmax[maxn<<2];
    int lmin[maxn<<2], rmin[maxn<<2];
    int sum[maxn<<2];
    
    void PushUp(int rt) {
        int l = rt<<1;
        int r = l+1;
        sum[rt] = sum[l] + sum[r];
        maxsub[rt] = max(max(maxsub[l], maxsub[r]), rmax[l]+lmax[r]);
        minsub[rt] = min(min(minsub[l], minsub[r]), rmin[l]+lmin[r]);
        lmax[rt] = max(lmax[l], sum[l]+lmax[r]);
        rmax[rt] = max(rmax[r], sum[r]+rmax[l]);
        lmin[rt] = min(lmin[l], sum[l]+lmin[r]);
        rmin[rt] = min(rmin[r], sum[r]+rmin[l]);
    }
    
    void build(int l, int r, int rt) {
        if (l == r) {
           scanf("%d", &sum[rt]);
           minsub[rt] = lmax[rt] = rmax[rt] = lmin[rt] = rmin[rt] = maxsub[rt] = sum[rt];
           return;
        }
        int m = (l+r)>>1;
        build(l, m, rt<<1);
        build(m+1, r, rt<<1|1);
        PushUp(rt);
    }
    
    void update(int target, int val, int l, int r, int rt) {
        if (l == r) {
            sum[rt] = maxsub[rt] = minsub[rt] = val;
            lmax[rt] = rmax[rt] = lmin[rt] = rmin[rt] = val;
            return;
        }
        int m = (l+r)>>1;
        if (m >= target) update(target, val, l, m, rt<<1);
        else update(target, val, m+1, r, rt<<1|1);
        PushUp(rt);
    }
    
    int main()
    {
        int n, m, ans;
    
        scanf ("%d", &n);
        build(1, n, 1);
        scanf("%d", &m);
        while (m--) {
            int a, b;
            scanf ("%d%d", &a, &b);
            update(a, b, 1, n, 1);
            if (sum[1] == maxsub[1]) //序列全为非负数的时候
                ans = sum[1] - minsub[1];
            else ans = max(maxsub[1], sum[1]-minsub[1]);
            printf ("%d
    ", ans);
        }
        return 0;
    }
  • 相关阅读:
    我喜欢的乐队-Descending
    SQL合并时间段的问题
    基本字符串相关函数,基本宏,内存相关函数,类型转换函数实现合集
    centos7.4 安装 .net core 2.2
    在Global.asax中 注册Application_Error事件 捕获全局异常
    一般后台系统数据库 用户权限设计
    API接口利用ActionFilterAttribute实现接口耗时检测
    Git 一般性操作
    tasks.json 配置 解决vscode控制台乱码问题
    iview发布到IIS 路由问题
  • 原文地址:https://www.cnblogs.com/0803yijia/p/3214758.html
Copyright © 2011-2022 走看看