(环状线段树)poj 2750 Potted Flower & poj 2886 Who Gets the Most Candies?

题目:
poj2750

题意:
给一个环状线段,有如下操作:
x v:修改位置 x 的值,使它的值为 v
修改完后输出这个环状线段的连续区间的值的最大和(最大区间不能是这个环本身)
在这里插入图片描述

思路:
连续区间的最大和 = 这个区间的 max(连续区间的最大和,这个区间的总和 - 连续区间的最小和)
线段树要记录:

  1. 这个区间的从左(右)边开始的连续区间的最大和
  2. 从左(右)边开始的连续区间的最小和
  3. 这个区间的总和
  4. 这个区间的连续区间的最大和和最小和

这个区间的连续区间的最大和 = max(这个区间的从左(右)边开始的连续区间的最大和,这个区间子树的连续区间的最大和,这个区间左子树的从右边开始的连续区间的最大和 + 右子树的从左边开始的连续区间的最大和)

这个区间的连续区间的最大和同理。

题目:
poj2886

题意:
类似于约瑟夫环问题,得到的糖果p = 出局的序号 x 的因数数量,输出最大得到糖果的名字

as:出局的序号为6,则它的因数是1,2,3,6,那么他得到的糖果为4(有4个因数)

思路:线段树 + 模拟
处理好第几个出局的位置

poj 2750 代码

#include <iostream>
#include <algorithm>
#define lson l, mid, pos << 1
#define rson mid + 1, r, pos << 1 | 1
using namespace std;
const int MAXN = 1e5 + 10;
struct node{
	//sum:间总和,lmax:从左边开始的连续区间的最大和,rmax:从右边开始的连续区间的最大和
	//lmin:从左边开始的连续区间的最小和,rmin:从右边开始的连续区间的最小和
	//nmax:这个区间的连续区间的最大和,mmin:这个区间的连续区间的最小和
	int sum, lmax, rmax, lmin, rmin, mmax, mmin;
}tree[MAXN<<2];  //环 => max or sum - min 
void updata(int p){
	tree[p].sum = tree[p<<1].sum + tree[p<<1|1].sum;
	tree[p].lmax = max(tree[p<<1].lmax, tree[p<<1].sum+tree[p<<1|1].lmax);
	tree[p].rmax = max(tree[p<<1|1].rmax, tree[p<<1|1].sum+tree[p<<1].rmax);
	tree[p].lmin = min(tree[p<<1].lmin, tree[p<<1].sum+tree[p<<1|1].lmin);
	tree[p].rmin = min(tree[p<<1|1].rmin, tree[p<<1|1].sum+tree[p<<1].rmin);
	tree[p].mmax = max(tree[p<<1].rmax+tree[p<<1|1].lmax, max(max(tree[p].lmax, tree[p].rmax), max(tree[p<<1].mmax, tree[p<<1|1].mmax)));
	tree[p].mmin = min(tree[p<<1].rmin+tree[p<<1|1].lmin, min(min(tree[p].lmin, tree[p].rmin), min(tree[p<<1].mmin, tree[p<<1|1].mmin)));
} 
void build(int l, int r, int pos){
	if (l == r){
		scanf("%d", &tree[pos].sum);
		tree[pos].lmax = tree[pos].lmin = tree[pos].mmax = tree[pos].mmin = tree[pos].rmax = tree[pos].rmin = tree[pos].sum;
		return;
	}
	int mid = (l + r) >> 1;
	build(lson);
	build(rson);
	updata(pos);
}
void add(int i, int v, int l, int r, int pos){
    if (l == r){
    	tree[pos].lmax = tree[pos].lmin = tree[pos].mmax = tree[pos].mmin = tree[pos].rmax = tree[pos].rmin = tree[pos].sum = v;
        return;
    }
    int mid = (l + r) >> 1;
	if (mid >= i)
		add(i, v, lson);
	else
		add(i, v, rson);
    updata(pos);
}
int main(){
	int n, m, x, v;
    scanf("%d", &n);
    build(1, n, 1);
    scanf("%d", &m);
	for (int i = 0; i < m; i++){
		scanf("%d%d", &x, &v);
		add(x, v, 1, n, 1);
		if (tree[1].sum == tree[1].mmax)
			printf("%d\n", tree[1].sum - tree[1].mmin);
		else
			printf("%d\n", max(tree[1].mmax, tree[1].sum - tree[1].mmin));
	}
    return 0;
}

poj 2886 代码

#include <iostream>
#include <algorithm>
#include <cmath>
#define lson l, mid, pos << 1
#define rson mid + 1, r, pos << 1 | 1
using namespace std;
const int MAXN = 5e5 + 10;
bool norprime[MAXN];
int prime[MAXN], pi;
int a[MAXN];
void prime_sieve(int n){  //欧拉筛
	norprime[0] = norprime[1] = true;
	for (int i = 2; i <= n; i++){
		if (!norprime[i])		
			prime[++pi] = i;
		for (int j = 1; j <= pi && i * prime[j] <= n; j++){	
			norprime[i * prime[j]] = true;	
			if (i % prime[j] == 0)		
				break;
		}
	}
}
int factor_count(int n){
	int ans = 1;
	int a;
	int k = sqrt(n*1.0) + 1;
	for(int i = 1; prime[i] < k; i++){
		if(n % prime[i] == 0){
			a = 0;
			while(n % prime[i] == 0){
				a++;
				n /= prime[i];
			}
			ans *= (a + 1);
		}
	}
	if(n > 1)
		ans <<= 1;
	return ans;
}
int tree[MAXN<<2];  //环 => idx + (要移动多少位 % 剩余人数) 
struct node{
	char a[12];
	int n;
}player[MAXN];
void updata(int p){
	tree[p] = tree[p<<1] + tree[p<<1|1];
} 
void build(int l, int r, int pos){
	if (l == r){
		tree[pos] = 1; 
		return;
	}
	int mid = (l + r) >> 1;
	build(lson);
	build(rson);
	updata(pos);
}
int addr(int s, int steps, int Size, int l, int r, int pos){
	tree[pos]--;
	if (l == r)
        return l;
    int mid = (l + r) >> 1;
	if (tree[pos<<1] - Size >= steps)
		return addr(s, steps, Size, lson);
	else
		return addr(l, steps-(tree[pos<<1]-Size), 0, rson);
}
int addl(int s, int steps, int Size, int l, int r, int pos){
	tree[pos]--;
	if (l == r)
        return l;
    int mid = (l + r) >> 1;
	if (tree[pos<<1|1] - Size >= steps)
		return addl(s, steps, Size, rson);
	else
		return addl(r, steps-(tree[pos<<1|1]-Size), 0, lson);
}
int find(int s, int e, int l, int r, int pos){
	if (s <= l && r <= e)
		return tree[pos];
	int mid = (l + r) >> 1;
	int ans = 0;
	if (mid >= s)
		ans += find(s, e, lson);
	if (mid < e)
		ans += find(s, e, rson);
	return ans;
}
int main(){
	int n, k, maxi, maxn;
	prime_sieve(MAXN);
    while (~scanf("%d%d", &n, &k)){
    	maxn = 0;
	    build(1, n, 1);
		for (int i = 0; i < n; i++){
			scanf(" %s", player[i].a);
			scanf("%d", &player[i].n);
		}
		for (int i = 0, idx = -1, Size, ans; i < n; ){  //k:表示在点idx向移动方向移动的最终值
			if (k >= 0){  //向右移
				k = k % (n - i);
				if (k == 0)
					k = n - i;
				Size = (i == 0) ? 0 : find(1, idx+1, 1, n, 1);
				if (tree[1] - Size >= k) 
					idx = addr(idx+1, k, Size, 1, n, 1) - 1;  //向右移没出界了
				else
					idx = addr(1, k-(tree[1]-Size), 0, 1, n, 1) - 1;  //向右移出界了
			}
			else{  /向左移
				k = -k % (n - i);
				if (k == 0)
					k = n - i;
				Size = (i == 0) ? 0 : find(idx+1, n, 1, n, 1);
				if (tree[1] - Size >= k)
					idx = addl(idx+1, k, Size, 1, n, 1) - 1;  //向左移没出界
				else
					idx = addl(n, k-(tree[1]-Size), 0, 1, n, 1) - 1;  //向左移出界了
			}
			i++;
			k = player[idx].n;
			ans = (a[i] == 0) ? factor_count(i) : a[i];
			if (maxn < ans){
				maxn = ans;
				maxi = idx;
			}
		}
    	printf("%s %d\n", player[maxi].a, maxn);
	}
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值