Yih的线段树(线段树计数)
题意
在线段树中,执行完build(1,1,n)
后,节点\(x\)被创建,且在所有被创建节点中,节点\(x\)的节点编号最大,则称\(x\)的编号是一个Yuzu数。
给定\(Q\)个数字\(x_i\),问\(x_i\)是否是Yuzu数。
题目链接:https://www.acwing.com/problem/content/4585/
数据范围
\(1 \leq Q \leq 10^5\)
\(1 \leq x_i \leq 10^9\)
思路
这道题赛场上做出来了,但是因为考过好几次了,所以在这里记录一下结论。
这种题就是打表找规律。规律如下:
首先我们将\(n = 2^k\)的情况,记为基准点。在基准点上,最大编号是\(2n-1\)。然后出现的最大编号是\(2n+1,3n+1,3n+\frac{n}{2}+1, 3n+\frac{n}{2}+\frac{n}{4}+1, \dots, 3n+\frac{n}{2}+\cdots + 4 + 1\)
代码
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <map>
using namespace std;
typedef long long ll;
map<ll, int> mp;
int main()
{
mp[1] = 1;
for(ll i = 2; i <= 1000000000; i *= 2) {
ll t = i * 4 - 1;
mp[2 * i - 1] = 1;
mp[2 * i + 1] = 1;
ll tmp = 3 * i + 1, p = i;
while(tmp < t) {
mp[tmp] = 1;
p /= 2;
tmp += p;
}
}
int T;
scanf("%d", &T);
while(T --) {
int x;
scanf("%d", &x);
if(mp[x]) puts("Y");
else puts("N");
}
return 0;
}