两种做法
主席树模板题 对两个版本的线段树进行区间查询 然后做差即可
#include <bits/stdc++.h>
using namespace std;
struct node
{
int nl;
int nr;
int val;
};
map <int,int> mp;
node tree[2000010];
int num[100010],pre[100010],root[100010];
int n,m,tot;
int build(int l,int r)
{
int cur,m;
cur=tot++;
tree[cur].nl=0,tree[cur].nr=0,tree[cur].val=0;
if(l==r) return cur;
m=(l+r)/2;
tree[cur].nl=build(l,m);
tree[cur].nr=build(m+1,r);
return cur;
}
int update(int rot,int tar,int l,int r)
{
int cur,m;
cur=tot++;
tree[cur]=tree[rot];
tree[cur].val++;
if(l==r) return cur;
m=(l+r)/2;
if(tar<=m) tree[cur].nl=update(tree[cur].nl,tar,l,m);
else tree[cur].nr=update(tree[cur].nr,tar,m+1,r);
return cur;
}
int query(int lrot,int rrot,int pl,int pr,int l,int r)
{
int res,cur,m;
if(pl<=l&&r<=pr)
{
return tree[rrot].val-tree[lrot].val;
}
res=0,m=(l+r)/2;
if(pl<=m) res+=query(tree[lrot].nl,tree[rrot].nl,pl,pr,l,m);
if(pr>m) res+=query(tree[lrot].nr,tree[rrot].nr,pl,pr,m+1,r);
return res;
}
int main()
{
int t,cas,q,i,l,r,h,p;
scanf("%d",&t);
for(cas=1;cas<=t;cas++)
{
scanf("%d%d",&n,&q);
for(i=1;i<=n;i++)
{
scanf("%d",&num[i]);
pre[i]=num[i];
}
sort(pre+1,pre+n+1);
mp.clear();
for(i=1,m=0;i<=n;i++)
{
if(m==0||pre[m]!=pre[i])
{
pre[++m]=pre[i];
mp[pre[m]]=m;
}
}
tot=0;
root[0]=build(1,n);
for(i=1;i<=n;i++)
{
root[i]=update(root[i-1],mp[num[i]],1,n);
}
printf("Case %d:\n",cas);
while(q--)
{
scanf("%d%d%d",&l,&r,&h);
l++,r++;
p=upper_bound(pre+1,pre+m+1,h)-pre-1;
if(p>=1) printf("%d\n",query(root[l-1],root[r],1,p,1,n));
else printf("0\n");
}
}
return 0;
}
线段树离线处理 把询问按h值排序 对每一个查询 把所有小于等于该查询h值的数都在线段树对应位置上更新
#include <bits/stdc++.h>
using namespace std;
struct node1
{
int l;
int r;
int val;
};
struct node2
{
int id;
int val;
};
struct node3
{
int l;
int r;
int h;
int id;
int val;
};
node1 tree[400010];
node2 ary[100010];
node3 order[100010];
int n,q;
bool cmpI(node2 n1,node2 n2)
{
return n1.val<n2.val;
}
bool cmpII(node3 n1,node3 n2)
{
return n1.h<n2.h;
}
bool cmpIII(node3 n1,node3 n2)
{
return n1.id<n2.id;
}
void build(int l,int r,int cur)
{
int m;
tree[cur].l=l;
tree[cur].r=r;
tree[cur].val=0;
if(l==r) return;
m=(l+r)/2;
build(l,m,2*cur);
build(m+1,r,2*cur+1);
}
void update(int tar,int cur)
{
tree[cur].val++;
if(tree[cur].l==tree[cur].r) return;
if(tar<=tree[2*cur].r) update(tar,2*cur);
else update(tar,2*cur+1);
}
int query(int pl,int pr,int cur)
{
int res;
if(pl<=tree[cur].l&&tree[cur].r<=pr)
{
return tree[cur].val;
}
res=0;
if(pl<=tree[2*cur].r) res+=query(pl,pr,2*cur);
if(pr>=tree[2*cur+1].l) res+=query(pl,pr,2*cur+1);
return res;
}
int main()
{
int t,cas,i,pos;
scanf("%d",&t);
for(cas=1;cas<=t;cas++)
{
scanf("%d%d",&n,&q);
for(i=1;i<=n;i++)
{
scanf("%d",&ary[i].val);
ary[i].id=i;
}
sort(ary+1,ary+n+1,cmpI);
for(i=1;i<=q;i++)
{
scanf("%d%d%d",&order[i].l,&order[i].r,&order[i].h);
order[i].l++,order[i].r++;
order[i].id=i;
}
sort(order+1,order+q+1,cmpII);
build(1,n,1);
pos=1;
for(i=1;i<=q;i++)
{
while(pos<=n&&ary[pos].val<=order[i].h)
{
update(ary[pos].id,1);
pos++;
}
order[i].val=query(order[i].l,order[i].r,1);
}
sort(order+1,order+q+1,cmpIII);
printf("Case %d:\n",cas);
for(i=1;i<=q;i++)
{
printf("%d\n",order[i].val);
}
}
return 0;
}