No Luck -- 主席树
作者:互联网
https://codeforces.com/gym/103388/problem/N
题目理解:
就是给了一个 \(3 \cdot 10^5\)的数组,大概 $ 3 \cdot 10^5$ 个查询,每次询问某个区间内数组中大于等于某个数的数有几个。
AC代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn = 300005;
int n,q,tot,rt[maxn],a[maxn];
struct chairman_tree
{
int son[2],siz;
} node[maxn*50];
void build(int &rt,int l,int r)
{
rt = ++tot;
if(l==r) return;
int mid = (l + r) >> 1;
build(node[rt].son[0],l,mid);
build(node[rt].son[1],mid+1,r);
}
void update(int &rt,int last,int l,int r,int val)
{
node[rt=++tot] = node[last];
++node[rt].siz;
if(l==r) return;
int mid = (l + r) >> 1;
if(val<=mid) update(node[rt].son[0],node[last].son[0],l,mid,val);
else update(node[rt].son[1],node[last].son[1],mid+1,r,val);
}
int query(int rt1,int rt2,int l,int r,int k) //询问 rt2-rt1所维护的区间内 大于等于k的数的数量
{
if(l==r) return l >= k ? node[rt2].siz-node[rt1].siz : 0;
int mid = (l+r) >> 1;
if(mid>=k) return node[node[rt2].son[1]].siz-node[node[rt1].son[1]].siz+
query(node[rt1].son[0],node[rt2].son[0],l,mid,k); //右子树的大小全部加上,继续询问左子树
else return query(node[rt1].son[1],node[rt2].son[1],mid+1,r,k); //继续询问右子树
}
signed main()
{
scanf("%d %d",&n,&q);
build(rt[0],0,100000); //在数据范围内建立权值线段树
for(int i=1;i<=n;++i)
{
scanf("%d",&a[i]);
update(rt[i],rt[i-1],0,100000,a[i]); //插入
}
int m,p,f;
for(int i=1;i<=q;++i)
{
scanf("%d %d %d",&m,&p,&f);
if(a[m]>=p) puts("0");
else{
int l = m + 1,r = m + f;
printf("%d\n",query(rt[l-1],rt[r],0,100000,p));
}
}
return 0;
}
标签:rt,node,No,--,siz,mid,son,int,Luck 来源: https://www.cnblogs.com/beiy/p/15899822.html