2022NOIP A层联测15 AB C D
【规律/数学】T1:给你值域在\([1,2^n]\)之间的数,要求你把他们分2组,使得每组\(sigma(ai^p),0<=p<n\)相等,输出构造方案。
考场
打表找规律,发现以4为一组对称构造就合法。
正解
不知道正解,但是考场没有删除调试!低错爆零!
点击查看代码
// ubsan: undefined
// accoders
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define rint register int
#define chu printf
#define ulll unsigned __int128
inline ll re() {
ll x = 0, h = 1;
char ch = getchar();
while (ch < '0' || ch > '9') {
if (ch == '-')
h = -1;
ch = getchar();
}
while (ch <= '9' && ch >= '0') {
x = (x << 1) + (x << 3) + (ch ^ 48);
ch = getchar();
}
return x * h;
}
const int N = (1 << 20) + 100;
bool vs[N]; //组是什么品种
bool chs[N]; //选不选
int one[N], two[N];
int n, k;
inline ll qpow(ll ar, ll br) {
ll cr = 1;
while (br) {
if (br & 1)
cr = cr * ar;
ar = ar * ar;
br >>= 1;
}
return cr;
}
inline void Group(int l, int r) //现在编号[l,r]区间
{
// chu("group:%d--%d\n",l,r);
if(r>(1<<13))
{
chu("shit\n");exit(0);
}
int mid = (l + r) >> 1;
for (rint i = 1; i <= mid; ++i) vs[i + mid] = !vs[i];
if (r == (1 << 13)) //到边界了
return;
Group(l, r * 2);
}
inline void Divide(int l, int r) {
int ir = l;
// chu("ir:%d bj:%d\n",ir,ir*8);
if (vs[l]) {
chs[8 * ir - 7] = chs[8 * ir - 4] = chs[8 * ir - 2] = chs[8 * ir - 1] = 1;
} else {
for (rint i = 8 * ir - 7; i <= 8 * ir; ++i) chs[i] = 1;
chs[8 * ir - 7] = chs[8 * ir - 4] = chs[8 * ir - 2] = chs[8 * ir - 1] = 0;
}
}
int main() {
// freopen("1.in","r",stdin);
// freopen("1.out","w",stdout);
freopen("sandalphon.in","r",stdin);
freopen("sandalphon.out","w",stdout);
n = re();
k = re();
// chu("%d %d\n",n,k);
if (n == 1) {
chu("1\n");
chu("1 1\n");
chu("1 2");
return 0;
}
if (n == 2) {
chu("1\n");
chu("2 1 4\n");
chu("2 2 3");
return 0;
}
vs[1] = 1; // 1是分合
Group(1, 2);
// chu("dont out\n");
for (rint i = 1; i <= (1 << 13); ++i) Divide(i, i);
chu("1\n");
//for(rint i=1;i<=10;++i)chu("%d ",chs[i]);chu("\n");
for (rint i = 1; i <= (1 << n); ++i)
if (chs[i])
one[++one[0]] = i;
else
two[++two[0]] = i;
chu("%d ", one[0]);
//for(rint i=1;i<=10;++i)chu("%d ",vs[i]);chu("\n");
for (rint i = 1; i <= one[0]; ++i) chu("%d ", one[i]);
chu("\n");
chu("%d ", two[0]);
for (rint i = 1; i <= two[0]; ++i) chu("%d ", two[i]);
chu("\n");
return 0;
}
/*
*/
【交互/图论/二分】T2:给你点数是n的图,你可以进行<=1e5次询问,询问边两端都在集合S中的边数,求最后图的边信息。(n<=2000)
考场
n^2枚举2个点有没有边
正解
固定一个点i,求·[1,i-1]中和它连的边,考虑快速求出,可以二分区间中和i连的点位置,因为[l,r]check(l,mid)=0,可以把l边界缩小到mid+1,这就是单调性了,\(O(2*m*logn)\),还是比较玄乎,考虑[1,i-1]的点边信息已经知道,维护前缀和就可以省略一次询问,-->\(m*logn\)
点击查看代码
// ubsan: undefined
// accoders
#include <bits/stdc++.h>
#include "YuukiAsuna.h"
using namespace std;
#define ll long long
#define ull unsigned long long
#define rint register int
#define chu printf
inline ll re() {
ll x = 0, h = 1;
char ch = getchar();
while (ch < '0' || ch > '9') {
if (ch == '-')
h = -1;
ch = getchar();
}
while (ch <= '9' && ch >= '0') {
x = (x << 1) + (x << 3) + (ch ^ 48);
ch = getchar();
}
return x * h;
}
const int N = 2000 + 100;
vector<pair<int,int> >ans;
vector<int>s;
bool mp[N][N];
int sum[N][N];
inline int Calc(int x,int y,int der)//找der在(x,y)集合的连边数量
{
if(x==y)
{
s.push_back(x);s.push_back(der);
int du=Query(s);
s.pop_back();s.pop_back();
return du;
}
for(rint i=x;i<=y;++i)s.push_back(i);
s.push_back(der);
int du=Query(s);
du=du-(sum[y][y]-sum[y][x-1]);
for(rint i=x;i<=y+1;++i)s.pop_back();
return du;
}
vector<pair<int, int> > Asuna(int n, int Q)
{
for(rint i=2;i<=n;++i)
{
int last=1,l,r;
int deg=Calc(1,i-1,i);//
for(rint j=1;j<=deg;++j)
{
l=last,r=i-1;
int nas=0;
while(l<=r)
{
int mid=(l+r)>>1;
if(Calc(last,mid,i))r=mid-1,nas=mid;
else l=mid+1;
}
mp[nas][i]=1;
last=nas+1;
}
int sp=0;
for(rint j=1;j<=i;++j)
{
sp+=mp[j][i];
sum[i][j]=sum[i-1][j]+sp;
}
sum[i][i]=sum[i-1][i-1]+sp;
}
for(rint i=1;i<=n;++i)
for(rint j=i+1;j<=n;++j)if(mp[i][j])ans.push_back(make_pair(i,j));
return ans;
}
/*
然后就是
*/
【数据结构:线段树维护区间和+覆盖性懒惰标记(渐进思想)】T3:给出一个实数序列A,opt=1:把[l,r]序列的数变成v;opt=2,把[l,r]取cos;opt=3,询问[l,r]区间和。(n,m<=3e5)
暴力(80tps)
cos进行>=45次趋近一个定值,所以记录lim是一个区间最少cos次数,如果>=45就不管它了;其他覆盖正常。
注意保证复杂度的优化【1】如果取cos时,已经有区间覆盖的标记直接变就行,不继续【2】cos更新必须彻底到叶子除非遇到【1】
\(O(m*logn*k)\),因为cos更新的复杂度不对。
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define rint register int
#define chu printf
inline ll re()
{
ll x=0,h=1;char ch=getchar();
while(ch<'0'||ch>'9')
{
if(ch=='-')h=-1;
ch=getchar();
}
while(ch<='9'&&ch>='0')
{
x=(x<<1)+(x<<3)+(ch^48);
ch=getchar();
}
return x*h;
}
const int N=3e5+100;
double a[N];
int n,m;
struct Segment_tree
{
#define lson (rt<<1)
#define rson (rt<<1|1)
double val[N<<2],tag[N<<2];//区间和,覆盖懒惰标记
int lim[N<<2];//迭代次数限制
inline void update(int rt,int l,int r,double cover,int dfs)
{
val[rt]=(r-l+1)*cover;
tag[rt]=cover;
lim[rt]=dfs;
}
inline void pushdown(int rt,int l,int mid,int r)
{
if(tag[rt]==1e9)return;
tag[lson]=tag[rson]=tag[rt];
val[lson]=(mid-l+1)*tag[rt];
val[rson]=(r-(mid+1)+1)*tag[rt];
lim[lson]=lim[rson]=lim[rt];//为什么?lim也需要从上到下,不然的话
tag[rt]=1e9;
}
inline void pushup(int rt)
{
val[rt]=val[lson]+val[rson];
lim[rt]=min(lim[lson],lim[rson]);
}
inline void build(int rt,int l,int r)
{
//chu("buildok:%d--%d\n",l,r);
tag[rt]=1e9;
if(l==r)
{
val[rt]=a[l];
lim[rt]=0;
return;
}
int mid=(l+r)>>1;
build(lson,l,mid);
build(rson,mid+1,r);
pushup(rt);
}
inline void insert_val(int rt,int l,int r,int L,int R,double d)
{
if(L<=l&&r<=R)
{
update(rt,l,r,d,0);
return;
}
int mid=(l+r)>>1;
pushdown(rt,l,mid,r);
if(L<=mid)insert_val(lson,l,mid,L,R,d);
if(R>mid)insert_val(rson,mid+1,r,L,R,d);
pushup(rt);
}
inline void insert_cos(int rt,int l,int r,int L,int R)
{
if(lim[rt]>=45)return;
if(L<=l&&r<=R&&tag[rt]!=1e9)
{
update(rt,l,r,cos(tag[rt]),lim[rt]+1);//原来有跌算
return;
}
if(l==r)
{
val[rt]=cos(val[rt]);
lim[rt]++;
return;
}
int mid=(l+r)>>1;
pushdown(rt,l,mid,r);
if(L<=mid)insert_cos(lson,l,mid,L,R);
if(R>mid)insert_cos(rson,mid+1,r,L,R);
pushup(rt);
}
inline double query(int rt,int l,int r,int L,int R)
{
if(L<=l&&r<=R)return val[rt];
int mid=(l+r)>>1;
double ret=0;
pushdown(rt,l,mid,r);
if(L<=mid)ret+=query(lson,l,mid,L,R);
if(R>mid)ret+=query(rson,mid+1,r,L,R);
return ret;
}
}t;
int main()
{
freopen("excalibur.in","r",stdin);
freopen("excalibur.out","w",stdout);
// freopen("1.in","r",stdin);
// freopen("1.out","w",stdout);
n=re(),m=re();
for(rint i=1;i<=n;++i)scanf("%lf",&a[i]);
t.build(1,1,n);
for(rint i=1;i<=m;++i)
{
int opt=re();
if(opt==3)
{
int l=re(),r=re();double var;
scanf("%lf",&var);
t.insert_val(1,1,n,l,r,var);
}
else if(opt==1)
{
int l=re(),r=re();
t.insert_cos(1,1,n,l,r);
}
else
{
int l=re(),r=re();
chu("%.13lf\n",t.query(1,1,n,l,r));
}
}
return 0;
}
/*
*/
trie树小专题
【trie树贪心/二分】T4:给出一个n个点的图,要求你连n条边,每条边的权值时2端点的异或值,求最小边权最大。(n<=5e5)
正解
发现一定时22配对不会失去最优解(已有方案删除边不会让答案更劣);
配对:二分答案,考虑每一位上的1能不能加上-->按照最优配对能不能不剩下点。
如果now位=1,方案唯一;
now位是0,贪心得让0和1配对,这样后面就没有要求了,可以随便消除,剩下不得不00或11的再配对。
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define rint register int
#define chu printf
inline ll re()
{
ll x=0,h=1;char ch=getchar();
while(ch<'0'||ch>'9')
{
if(ch=='-')h=-1;
ch=getchar();
}
while(ch<='9'&&ch>='0')
{
x=(x<<1)+(x<<3)+(ch^48);
ch=getchar();
}
return x*h;
}
const int N=5e5+100;
int ch[N*31][2],tot=1;
int n,a[N],siz[N*31];
#define ls(rt) ch[rt][0]
#define rs(rt) ch[rt][1]
inline int solve(int u,int v,int dep,int lim)
{
if(!u||!v)return siz[u]+siz[v];
if(dep<0)return 0;
//如果这一位要求是1
if((lim>>dep)&1)
{
if(dep==0)
return abs(siz[ls(u)]-siz[rs(v)])+abs(siz[ls(v)]-siz[rs(u)]);
return solve(ls(u),rs(v),dep-1,lim)+solve(ls(v),rs(u),dep-1,lim);
}
if(siz[ls(u)]>siz[rs(v)]&&siz[rs(u)]>siz[ls(v)])return siz[u]-siz[v];
if(siz[ls(u)]<=siz[rs(v)]&&siz[rs(u)]<=siz[ls(v)])return siz[v]-siz[u];
int tot0=siz[ls(u)]+siz[ls(v)],tot1=siz[rs(u)]+siz[rs(v)];
if(tot0<tot1)
{
int w=solve(rs(u),rs(v),dep-1,lim);
return max(w-tot0,abs(siz[u]-siz[v]));
}
else
{
int w=solve(ls(u),ls(v),dep-1,lim);
return max(w-tot1,abs(siz[u]-siz[v]));
}
}
int main()
{
freopen("win.in","r",stdin);
freopen("win.out","w",stdout);
// freopen("1.in","r",stdin);
// freopen("1.out","w",stdout);
n=re();
for(rint i=1;i<=n;++i)
{
a[i]=re();
int now=1;
for(rint j=30;j>=0;--j)
{
siz[now]++;
bool chr=(a[i]>>j)&1;
if(ch[now][chr]==0)ch[now][chr]=++tot;
now=ch[now][chr];
}
siz[now]++;
}
int ans=0;
for(rint i=30;i>=0;--i)
{
if(solve(1,1,30,ans+(1<<i))==0)ans=ans+(1<<i);
}
chu("%d",ans);
return 0;
}
/*
*/
【trie树:最小生成树/神仙pushup结合预处理】模板:求给出的序列22异或最小值,只有不同颜色的可以异或,而且带修改。
【1】生成树:在dfs你的trie树模拟找联通块的边(最小边权)过程,启发式合并把节点集合传递到根。
点击查看代码
// ubsan: undefined
// accoders
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define rint register int
#define chu printf
inline ll re() {
ll x = 0, h = 1;
char ch = getchar();
while (ch < '0' || ch > '9') {
if (ch == '-')
h = -1;
ch = getchar();
}
while (ch <= '9' && ch >= '0') {
x = (x << 1) + (x << 3) + (ch ^ 48);
ch = getchar();
}
return x * h;
}
const int N = 2e5 + 100;
int tr[N * 30][2], n, m, a[N], cor[N], store[N * 30], tot; //值和颜色
vector<int> contain[N * 30]; //记录每个节点内部联通点集
vector<int> g[N]; //记录生成树
multiset<int> s;
inline void add_dot(int x, int y) {
if (!x || !y)
return;
g[x].push_back(y);
g[y].push_back(x);
// chu("pos:%d %d:ins:%d %d\n",x,y,a[x],a[y]);
if (cor[x] != cor[y])
s.insert(a[x] ^ a[y]);
}
inline void ins_trie(int x, int id) {
int now = 1;
// chu("insert:%d %d\n",x,id);
for (rint i = 29; i >= 0; --i) {
bool ch = ((x >> i) & 1);
if (!tr[now][ch])
tr[now][ch] = ++tot;
now = tr[now][ch];
}
if (store[now])
add_dot(id, store[now]);
store[now] = id;
}
inline int find_trie(int x) {
int now = 1;
for (rint i = 29; i >= 0; --i) {
bool chr = (x >> i) & 1;
if (tr[now][chr])
now = tr[now][chr];
else
now = tr[now][!chr];
}
return store[now];
}
inline void dfs_trie(int now, int pos) {
if (tr[now][0])
dfs_trie(tr[now][0], pos - 1);
if (tr[now][1])
dfs_trie(tr[now][1], pos - 1);
if (!tr[now][0] && !tr[now][1]) {
contain[now].push_back(store[now]);
return;
}
if (!tr[now][0] || !tr[now][1]) {
if (!tr[now][0])
swap(contain[now], contain[tr[now][1]]);
if (!tr[now][1])
swap(contain[now], contain[tr[now][0]]);
return;
}
if (contain[tr[now][0]].size() > contain[tr[now][1]].size())
swap(contain[tr[now][0]], contain[tr[now][1]]);
int res1 = 0, res2 = 0, Min = 2147483647;
for (rint i = 0; i < contain[tr[now][0]].size(); ++i) {
int u = contain[tr[now][0]][i];
int v = find_trie(a[u] ^ (1 << pos));
if (v && Min > (a[u] ^ a[v])) //连最小的边
{
Min = a[u] ^ a[v];
res1 = u, res2 = v;
}
}
add_dot(res1, res2); //启发合并
swap(contain[now], contain[tr[now][1]]); // g该放的都放了啊
for (rint i = 0; i < contain[tr[now][0]].size(); ++i) {
int u = contain[tr[now][0]][i];
contain[now].push_back(u);
}
}
int main() {
freopen("who.in", "r", stdin);
freopen("who.out", "w", stdout);
// freopen("who.in","r",stdin);
// freopen("who.out","w",stdout);
tot = 1;
n = re(), m = re();
for (rint i = 1; i <= n; ++i) a[i] = re();
for (rint i = 1; i <= n; ++i) cor[i] = re();
for (rint i = 1; i <= n; ++i) ins_trie(a[i], i);
dfs_trie(1, 29); //默认1是虚点,不然怕出问题
// chu("insert:%d\n",s.size());
for (rint i = 1; i <= m; ++i) {
int x = re(), y = re();
if (cor[x] != y) //如果颜色真的改了
{
for (rint j = 0; j < g[x].size(); ++j) {
int connect = g[x][j];
if (cor[connect] == cor[x]) //现在不一样了
{
s.insert(a[connect] ^ a[x]);
}
if (cor[connect] == y) {
s.erase(s.find(a[connect] ^ a[x]));
}
}
}
cor[x] = y;
chu("%d\n", *s.begin());
}
return 0;
}
/*
5 2
1 2 3 4 5
1 1 1 2 1
4 3
5 3
*/
【2】预处理:直接把答案在trie树维护,叶子节点记录颜色和出现次数,map映射,修改一条路径的值,维护mini
点击查看代码
// ubsan: undefined
// accoders
#include <bits/stdc++.h>
typedef long long ll;
typedef unsigned long long ull;
typedef double db;
typedef long double ldb;
#define fre(x) freopen(#x ".in", "r", stdin), freopen(#x ".out", "w", stdout)
#define Rep(i, a, b) for (int i = a; i <= b; ++i)
#define Dwn(i, a, b) for (int i = a; i >= b; --i)
#define pii pair<int, int>
#define mair make_pair
#define fir first
#define sec second
using namespace std;
const int maxn = 2e5 + 10, INF = 2e9, B = 30;
char buf[1 << 20], *p1, *p2;
char gc() { return p1 == p2 && (p2 = buf + fread(p1 = buf, 1, 1 << 20, stdin), p1 == p2) ? EOF : *p1++; }
int read() {
int x = 0;
bool f = 0;
char c = gc();
while (!isdigit(c)) {
if (c == '-')
f = 1;
c = gc();
}
while (isdigit(c)) x = x * 10 + (c ^ 48), c = gc();
return f ? -x : x;
}
int n, m;
int a[maxn];
int col[maxn];
bool fg;
map<int, int> Map[maxn];
struct Te {
#define lch ch[u][0]
#define rch ch[u][1]
int ch[maxn * 80][2];
int id[maxn * 80];
int val[maxn * 80], mini[maxn * 80];
bool same[maxn * 80];
int color[maxn * 80];
int tot;
int root;
Te() {
tot = 1;
root = 1;
memset(val, 0x3f, sizeof(val)), memset(mini, 0x3f, sizeof(mini));
}
void Pushup(int u) {
if (!lch) {
if (same[rch])
same[u] = true, color[u] = color[rch], mini[u] = INF;
else
mini[u] = mini[rch], same[u] = false;
return;
}
if (!rch) {
if (same[lch])
same[u] = true, color[u] = color[lch], mini[u] = INF;
else
mini[u] = mini[lch], same[u] = false;
return;
}
if (same[lch] && same[rch]) {
if (color[lch] == color[rch]) {
same[u] = true;
color[u] = color[lch];
} else
same[u] = false, mini[u] = val[u];
return;
}
same[u] = false;
mini[u] = INF;
if (!same[lch])
mini[u] = min(mini[u], mini[lch]);
if (!same[rch])
mini[u] = min(mini[u], mini[rch]);
}
int Min(int u, int x, int k) {
if (!u)
return INF;
int res = 0;
for (int i = k; i >= 0; --i) {
int c = (x >> i) & 1;
if (ch[u][c])
u = ch[u][c];
else
u = ch[u][c ^ 1], res |= 1 << i;
}
return res;
}
void Insert(int x) {
int u = root;
Dwn(i, B, 0) {
int c = (x >> i) & 1;
if (!ch[u][c])
ch[u][c] = ++tot;
if (c) {
if (i)
val[u] = min(val[u], Min(ch[u][c ^ 1], x, i - 1) | (1 << i));
else
val[u] = ch[u][c ^ 1] ? 1 : INF;
}
u = ch[u][c];
}
if (!id[u])
id[u] = ++id[0];
}
void Add(int x, int cls) {
int u = root;
vector<int> vec;
Dwn(i, B, 0) {
vec.emplace_back(u);
int c = (x >> i) & 1;
u = ch[u][c];
}
Map[id[u]][cls]++;
if (Map[id[u]].size() == 1) {
same[u] = true;
color[u] = (*Map[id[u]].begin()).fir;
} else {
same[u] = false;
mini[u] = 0;
}
reverse(vec.begin(), vec.end());
for (auto p : vec) Pushup(p);
}
void Del(int x, int cls) {
int u = root;
vector<int> vec;
Dwn(i, B, 0) {
vec.emplace_back(u);
int c = (x >> i) & 1;
u = ch[u][c];
}
Map[id[u]][cls]--;
if (Map[id[u]][cls] == 0)
Map[id[u]].erase(cls);
if (Map[id[u]].size() == 1) {
same[u] = true;
color[u] = (*Map[id[u]].begin()).fir;
} else {
same[u] = false;
mini[u] = 0;
}
reverse(vec.begin(), vec.end());
for (auto p : vec) Pushup(p);
}
void Pre(int u) {
if (lch)
Pre(lch);
if (rch)
Pre(rch);
if (lch || rch)
Pushup(u);
}
void Modify(int x, int np, int nw) {
int u = root;
vector<int> vec;
Dwn(i, B, 0) {
vec.emplace_back(u);
int c = (x >> i) & 1;
u = ch[u][c];
}
Map[id[u]][np]--;
if (Map[id[u]][np] == 0)
Map[id[u]].erase(np);
Map[id[u]][nw]++;
if (Map[id[u]].size() == 1) {
same[u] = true;
color[u] = (*Map[id[u]].begin()).fir;
} else {
same[u] = false;
mini[u] = 0;
}
reverse(vec.begin(), vec.end());
for (auto p : vec) Pushup(p);
}
} T;
void solve() {
fre(who);
n = read(), m = read();
Rep(i, 1, n) a[i] = read();
Rep(i, 1, n) col[i] = read();
Rep(i, 1, n) T.Insert(a[i]);
Rep(i, 1, n) T.Add(a[i], col[i]);
// T.Pre(T.root);
while (m--) {
int x, y;
x = read(), y = read();
T.Modify(a[x], col[x], y);
col[x] = y;
printf("%d\n", T.mini[T.root]);
}
}
int main() { return solve(), 0; }
【trie树贪心构造】https://www.luogu.com.cn/problem/CF1446C
把节点加入trie树,从叶子合并到根,维护函数\(f[rt]\)表示到rt子树内的合法的最多保留点,如果对于第k位只有一个位有值直接递归;否则对于lson和rson取max+1:因为lson保留>1那么rson保留最多1,这样不会让答案更多,所以保留一个不失去最优,再从!k位选一个一定不会增加互为相同。
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define rint register int
#define ll long long
#define ull unsigned long long
#define chu printf
inline ll re()
{
ll x=0,h=1;char ch=getchar();
while(ch<'0'||ch>'9')
{
if(ch=='-')h=-1;
ch=getchar();
}
while(ch<='9'&&ch>='0')
{
x=(x<<1)+(x<<3)+(ch^48);
ch=getchar();
}
return x*h;
}
const int N=2e5+100;
int n,a[N];
int tr[N*30][2],tot=1;//2^29就够了
inline void ins(int x)
{
int now=1;
for(rint i=29;i>=0;--i)
{
bool ch=(x>>i)&1;
if(!tr[now][ch])tr[now][ch]=++tot;
now=tr[now][ch];
}
}
inline int del(int rt)
{
if(!tr[rt][0]&&!tr[rt][1])return 1;
if(!tr[rt][0])return del(tr[rt][1]);
if(!tr[rt][1])return del(tr[rt][0]);
return max(del(tr[rt][1]),del(tr[rt][0]))+1;
}
int main()
{
//("1.in","r",stdin);
//freopen("1.out","w",stdout);
//freopen("1.in","r",stdin);
//freopen("1.out","w",stdout);
n=re();
for(rint i=1;i<=n;++i)
a[i]=re();
for(rint i=1;i<=n;++i)
{
ins(a[i]);
}
chu("%d",n-del(1));
return 0;
}
/*
5
0 1 5 2 6
7
6 9 8 7 3 5 2
*/
trie树贪心一般从低到高递归选择处理