算一道比较水的线段树,用树状数组应该也可以,但是感觉操作起来比线段树麻烦。我的思路是维护区间的和,然后根据输入的rank由根到底查,可和左儿子比较大小然后决定向左走还是向右走,直到底部输出index,1A了,感觉不错,哈哈
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
namespace
{
const int MAX_N = (1 << 18) - 1;
int n, N, K, q;
int *dat = new int[MAX_N];
int init(int index)
{
if (index < n - 1)
return dat[index] = init(2 * index + 1) + init(2 * index + 2);
else
return dat[index];
}
void input()
{
memset(dat, 0, sizeof(int) * MAX_N);
n = 1;
while (n < N)
n <<= 1;
int index = n - 1;
for (int i = 0; i < N; i++)
scanf("%d", &dat[index++]);
init(0);
}
void update(int a, int b)
{
int index = a + n - 2;
dat[index] = b;
while (index)
{
index = (index - 1) >> 1;
dat[index] = dat[2 * index + 1] + dat[2 * index + 2];
}
}
void solve()
{
int index = 0, l;
while (index < n - 1)
{
l = dat[index * 2 + 1];
if (q > l)
{
index = index * 2 + 2;
q -= l;
}
else
index = index * 2 + 1;
}
printf("%d\n", index - n + 2);
}
}
int main()
{
char s[2];
int a, b;
while (scanf("%d", &N) != EOF)
{
input();
scanf("%d", &K);
while (K--)
{
scanf("%s", s);
if (s[0] == 'p')
{
scanf("%d %d", &a, &b);
update(a, b);
}
else
{
scanf("%d", &q);
solve();
}
}
}
}