题目:
poj2750
题意:
给一个环状线段,有如下操作:
x v:修改位置 x 的值,使它的值为 v
修改完后输出这个环状线段的连续区间的值的最大和(最大区间不能是这个环本身)
思路:
连续区间的最大和 = 这个区间的 max(连续区间的最大和,这个区间的总和 - 连续区间的最小和)
线段树要记录:
- 这个区间的从左(右)边开始的连续区间的最大和
- 从左(右)边开始的连续区间的最小和
- 这个区间的总和
- 这个区间的连续区间的最大和和最小和
这个区间的连续区间的最大和 = 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;
}