求区间不同数的个数:
/*
5
1 1 2 1 3
3
1 5 (3)
2 4 (2)
3 5 (3)
*/
#include<bits/stdc++.h>
#define ll long long int
using namespace std;
const int maxn=2e5+10;
const int maxm=1e6+10;
ll read(){
ll x=0,f=1;char ch=getchar();
while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int n, q;
int cnt;
struct node{
int l,r;
int sum;
}t[maxn * 20];
int root[maxn];
int last[maxm],pre[maxn];
void update(int pos,int &rt,int l,int r){
t[++cnt]=t[rt];
rt=cnt;
t[rt].sum++;
if(l==r) return ;
int mid=(l+r)>>1;
if(pos<=mid) update(pos,t[rt].l,l,mid);
else update(pos,t[rt].r,mid+1,r);
}
int query(int x,int y,int l,int r,int ql,int qr){
if(ql<=l&&r<=qr) return t[y].sum-t[x].sum;
else{
int mid=(l+r)>>1,ans=0;
if(ql<=mid) ans+=query(t[x].l,t[y].l,l,mid,ql,qr);
if(mid<qr) ans+=query(t[x].r,t[y].r,mid+1,r,ql,qr);
return ans;
}
}
int main(){
n=read();
for(int i=1;i<=n;i++){
int x=read();
pre[i]=last[x];
last[x]=i;
}
for(int i=1;i<=n;i++){
root[i]=root[i-1];
update(pre[i],root[i],0,n);
}
q=read();
while(q--){
int ql=read(),qr=read();
printf("%d\n",query(root[ql-1],root[qr],0,n,0,ql-1));
}
return 0;
}
求区间第k小:
/*
7 3
1 5 2 6 3 7 4
2 5 3 (5)
4 4 1 (6)
1 7 3 (3)
*/
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 10;
int n, m;
int cnt;
struct node{
int L, R;//分别指向左右子树
int sum;//该区间内有多少个数
}Tree[maxn * 20];
struct value{
int x;//值的大小
int id;//离散之前在原数组中的位置
}Value[maxn];
bool cmp(value v1, value v2)
{
return v1.x < v2.x;
}
int root[maxn];//多颗线段树的根节点
int arr[maxn];//原数组离散之后的数组
void update(int num, int &rt, int l, int r)
{
Tree[cnt++] = Tree[rt];
rt = cnt - 1;
Tree[rt].sum++;
if(l == r) return;
int mid = (l + r)>>1;
if(num <= mid) update(num, Tree[rt].L, l, mid);
else update(num, Tree[rt].R, mid + 1, r);
}
int query(int i, int j, int k, int l, int r)
{
int d = Tree[Tree[j].L].sum - Tree[Tree[i].L].sum;
if(l == r) return l;
int mid = (l + r)>>1;
if(k <= d) return query(Tree[i].L, Tree[j].L, k, l, mid);
else return query(Tree[i].R, Tree[j].R, k - d, mid + 1, r);
}
int main()
{
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i++)
{
scanf("%d", &Value[i].x);
Value[i].id = i;
}
//进行离散化
sort(Value + 1, Value + n + 1, cmp);
for(int i = 1; i <= n; i++)
{
arr[Value[i].id] = i;
}
cnt=1;
for(int i = 1; i <= n; i++)
{
root[i] = root[i - 1];
update(arr[i], root[i], 1, n);
}
int left, right, k;
for(int i = 1; i <= m; i++)
{
scanf("%d%d%d", &left, &right, &k);
printf("%d\n", Value[query(root[left - 1], root[right], k, 1, n)].x);
}
return 0;
}
求带修改的区间第k小:
/*
5 3
3 2 1 4 7
Q 1 4 3 (3)
C 2 6
Q 2 5 3 (6)
*/
#include<bits/stdc++.h>
using namespace std;
int use[maxn*10],n,m,size,tot=0,all=0,h[maxn*10],v[maxn*10],t[maxn*10];
struct chairtree{
int l,r,size;
}a[maxn*300];
struct question{
int l,r,k;
}q[maxn];
int lowbit(int x){
return x&(-x);
}
void Hash1(){
sort(h+1,h+1+all);
size=unique(h+1,h+1+all)-h-1;
}
int Hash(int x){
return lower_bound(h+1,h+1+size,x)-h;
}
int Build(int l,int r){
int now=++tot;
a[now].size=0;
if (l==r) return now;
int m=(l+r)>>1;
a[now].l=Build(l,m);
a[now].r=Build(m+1,r);
return now;
}
int Update(int root,int p,int val){
int now=++tot,tmp=now;
int l=1,r=size;
a[now].size=a[root].size+val;
while (l<r){
int m=(l+r)>>1;
if (p<=m){
a[now].l=++tot;
a[now].r=a[root].r;
root=a[root].l;
now=a[now].l;
r=m;
}
else{
a[now].l=a[root].l;
a[now].r=++tot;
root=a[root].r;
now=a[now].r;
l=m+1;
}
a[now].size=a[root].size+val;
}
return tmp;
}
void Add(int x,int p,int val){
for (int i=x;i<=n;i+=lowbit(i)) //树状数组只需修改logn个
t[i]=Update(t[i],p,val);
}
int Getsum(int x){
int ans=0;
for (int i=x;i;i-=lowbit(i))
ans+=a[a[use[i]].l].size;
return ans;
}
int Query(int lx,int rx,int k){
int l=1,r=size;
for (int i=lx-1;i;i-=lowbit(i)) use[i]=t[i];
for (int i=rx;i;i-=lowbit(i)) use[i]=t[i];
while (l<r){
int m=(l+r)>>1;
int tmp=Getsum(rx)-Getsum(lx-1);
if (tmp>=k){
for (int i=lx-1;i;i-=lowbit(i))
use[i]=a[use[i]].l;
for (int i=rx;i;i-=lowbit(i))
use[i]=a[use[i]].l;
r=m;
}
else{
for (int i=lx-1;i;i-=lowbit(i))
use[i]=a[use[i]].r;
for (int i=rx;i;i-=lowbit(i))
use[i]=a[use[i]].r;
k-=tmp;
l=m+1;
}
}
return l;
}
int main(){
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++)
scanf("%d",&v[i]),h[i]=v[i];
all=n;
for (int i=1;i<=m;i++){
char str[10];
int l,r,k;
scanf("%s",str);
if (str[0]=='Q'){
scanf("%d%d%d",&l,&r,&k);
q[i].l=l,q[i].r=r,q[i].k=k;
}
else{
scanf("%d%d",&r,&k);
q[i].l=0,q[i].r=r,q[i].k=k;
h[++all]=k;
}
}
Hash1();
t[0]=Build(1,size);
for (int i=1;i<=n;i++)
t[i]=t[0];
for (int i=1;i<=n;i++)
Add(i,Hash(v[i]),1);
for (int i=1;i<=m;i++){
if (q[i].l)
printf("%d\n",h[Query(q[i].l,q[i].r,q[i].k)]);
else{
Add(q[i].r,Hash(v[q[i].r]),-1);
Add(q[i].r,Hash(q[i].k),1);
v[q[i].r]=q[i].k;
}
}
return 0;
}