题目链接:http://poj.org/problem?id=2886
这题题意就非常迷,to left , to right 竟然是顺时针和逆时针的意思
WTF!!!
预处理一下1-n的不同的因子个数
然后线段树维护一下区间内剩下的人数就可以了,主要是找到去掉的人在剩下的人里选第几个
如果是正的那么 顺时针第val个 就让当前位置pos+val - 1 然后对剩下的人数取模,为什么-1呢,因为你把pos位置的人已经去掉了,所以需要从pos-1位置开始数val个人
如果是负的,逆时针-val个,就让当前位置pos+val 然后对剩下的人数取模 + 人数 然后再取模(减法取模注意会出现负数),这次为什么不-1呢,因为你把pos位置的人已经去掉了,所以需要从pos位置往前开始数-val个人
如果算出来的位置是0那么去掉的一定是末尾那个人,直接让他等于剩下的人数就好了
#include <iostream>
#include <cstdio>
using namespace std;
const int maxn = 5e5 + 10;
struct Tree {
int l, r, val;
}e[maxn << 2];
struct node{
char a[12];
int id;
}a[maxn];
void build(int l, int r, int cur){
e[cur].l = l;
e[cur].r = r;
e[cur].val = r - l + 1;
if(l == r) return;
int mid = l + r >> 1;
build(l, mid, cur << 1);
build(mid + 1, r, cur << 1 | 1);
}
int update(int l, int r, int cur, int pos){
if(l == r) {
e[cur].val--;
return l;
}
int mid = l + r >> 1;
int ans;
if(pos <= e[cur << 1].val) ans = update(l, mid, cur << 1, pos);
else ans = update(mid + 1, r, cur << 1 | 1, pos - e[cur << 1].val);
e[cur].val = e[cur << 1].val + e[cur << 1 | 1].val;
return ans;
}
int pre[maxn];
void prev(){
for(int i = 1; i < maxn; i++) {
pre[i]++;
for(int j = i + i; j < maxn; j += i)
pre[j]++;
}
}
int main(){
int n, k;
prev();
while(~scanf("%d%d", &n, &k)){
build(1, n, 1);
for(int i = 1; i <= n; i++) {
scanf("%s %d", a[i].a, &a[i].id);
}
int res = 0, id;
for(int i = 1; i <= n; i++) {
int s = update(1, n, 1, k);
//cout << s <<endl;
if(pre[i] > res) {
res = pre[i];
id = s;
}
if(i == n) break;
if(a[s].id > 0){
k = (a[s].id + k - 1) % e[1].val;
}
else {
k = ((a[s].id + k) % e[1].val + e[1].val) % e[1].val;
}
if(k == 0) k = e[1].val;
}
printf("%s %d\n", a[id].a, res);
}
return 0;
}