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;
    }
  • 相关阅读:
    alert
    自定义基类装载数据模块显示到dataGrid
    关于dataGrid查询按钮的实现
    如何查看oracle用户具有的权限和角色 大风起
    LoadRunner使用手册 大风起
    电脑蓝屏了,教你一招保证恢复 大风起
    oracle如何查看当前有哪些用户连接到数据库 大风起
    apache+tomcat整合(动静分离) 大风起
    cdn技术浅谈 大风起
    Tomcat性能优化总结 大风起
  • 原文地址:https://www.cnblogs.com/0803yijia/p/3214758.html
Copyright © 2011-2022 走看看