紫书训练 7.17

https://vjudge.net/contest/311900#overview 树状数组+主席数

密码996996 

A - HH的项链

先按r排序,然后每次清除该数前面已经出现的位置,增加它新出现的位置。然后查询。


#include<bits/stdc++.h>
#define il inline
#define pb push_back
#define fi first
#define se second
#define ms(_data,v) memset(_data,v,sizeof(_data))
#define sc(n) scanf("%d",&n)
#define SC(n,m) scanf("%d %d",&n,&m)
#define SZ(a) int((a).size())
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define drep(i,a,b)	for(int i=a;i>=b;--i)
using namespace std;
typedef long long ll;
const ll inf=0x3f3f3f3f;
const double PI=acos(-1.0);
const double eps=1e-9;
const int maxn=5e4+5;
const int maxm=1e6+5;
int a[maxn],sum[maxm],pre[maxm],ans[maxn<<2],n,m;
struct node{
	int l,r,id;
}q[maxn<<2];
bool cmp(node x,node y){
	return x.r<y.r;
}
void add(int p,int x){
    while(p<=n) sum[p]+=x,p+=p&-p;
}
int ask(int p){ 
    int res=0;
    while(p) res+=sum[p],p-=p&-p;
    return res;
}
int main(){
	sc(n);
	rep(i,1,n) sc(a[i]);
	sc(m);
	rep(i,1,m){
		SC(q[i].l,q[i].r);
		q[i].id=i;
	}
	sort(q+1,q+m+1,cmp);
	rep(i,1,m){
		rep(j,q[i-1].r+1,q[i].r){
			if(pre[a[j]]) add(pre[a[j]],-1);
			pre[a[j]]=j,add(pre[a[j]],1);
		}
		ans[q[i].id]=ask(q[i].r)-ask(q[i].l-1);
	}
	rep(i,1,m) printf("%d\n",ans[i]);
	return 0;
}

B - K-th Number

主席数模板题

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<string>
#include<cstring>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<cmath>
#include<sstream>
//#include<bits/stdc++.h>
#define il inline
#define pb push_back
#define fi first
#define se second
#define ms(_data,v) memset(_data,v,sizeof(_data))
#define sc(n) scanf("%d",&n)
#define SC(n,m) scanf("%d %d",&n,&m)
#define SZ(a) int((a).size())
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define drep(i,a,b)	for(int i=a;i>=b;--i)
using namespace std;
typedef long long ll;
const ll inf=0x3f3f3f3f;
const double PI=acos(-1.0);
const double eps=1e-9;
const int maxn=1e5+5;
int a[maxn],b[maxn],rt[maxn*20],ls[maxn*20],rs[maxn*20],sum[maxn*20];
int n,m,tot;
void build(int &rt,int l,int r){
	rt=++tot;
	sum[rt]=0;
	if(l==r) return;
	int mid=(l+r)>>1;
	build(ls[rt],l,mid);
	build(rs[rt],mid+1,r); 
}
void update(int &rt,int l,int r,int last,int p){
	rt=++tot;
	ls[rt]=ls[last],rs[rt]=rs[last];
	sum[rt]=sum[last]+1;
	if(l==r) return;
	int mid=(l+r)>>1;
	if(p<=mid) update(ls[rt],l,mid,ls[last],p);
	else update(rs[rt],mid+1,r,rs[last],p);
}
int query(int ss,int ee,int l,int r,int k){
	if(l==r) return l;
	int mid=(l+r)>>1;
	int cnt=sum[ls[ee]]-sum[ls[ss]];
	if(k<=cnt) return query(ls[ss],ls[ee],l,mid,k);
	else return query(rs[ss],rs[ee],mid+1,r,k-cnt);
}
int main(){
	SC(n,m);
	rep(i,1,n) sc(a[i]),b[i]=a[i];
	sort(b+1,b+n+1);
	int sz=unique(b+1,b+n+1)-(b+1);
	build(rt[0],1,sz);
	rep(i,1,n){
		a[i]=lower_bound(b+1,b+sz+1,a[i])-b; 
		update(rt[i],1,sz,rt[i-1],a[i]);	
	} 
	int l,r,k;
	rep(i,1,m){
		sc(l),sc(r),sc(k);
		int id=query(rt[l-1],rt[r],1,sz,k);
		printf("%d\n",b[id]);
	} 
	return 0;
}

C - Dynamic Rankings

 待修改的主席数,俺也是才学。过了luogu上的这道题,但是这个一直段错误,难受,不知道原因。

#include<bits/stdc++.h>
#define il inline
#define pb push_back
#define fi first
#define se second
#define ms(_data,v) memset(_data,v,sizeof(_data))
#define sc(n) scanf("%d",&n)
#define SC(n,m) scanf("%d %d",&n,&m)
#define SZ(a) int((a).size())
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define drep(i,a,b)	for(int i=a;i>=b;--i)
using namespace std;
typedef long long ll;
const ll inf=0x3f3f3f3f;
const double PI=acos(-1.0);
const double eps=1e-9;
const int maxn=1e5+5;
unordered_map<int,int> rk;
int T,n,m,tot,sz,a[maxn],b[maxn*5];
struct tree{
	int l,r,x;
}t[maxn*900];
int root[maxn],root1[maxn],cnt,tot1,tot2,q1[maxn],q2[maxn];
il int update(int l,int r,int last,int k,int op){
	int rt=++cnt;
	t[rt]=t[last],t[rt].x+=op;
	if(l==r) return rt;
	int mid=(l+r)>>1;
	if(k<=mid) t[rt].l=update(l,mid,t[last].l,k,op);
	else t[rt].r=update(mid+1,r,t[last].r,k,op);
	return rt;
}
il int query(int l,int r,int s1,int s2,int k){
	if(l==r) return l;
	int x=t[t[s2].l].x-t[t[s1].l].x;
	rep(i,1,tot1) x-=t[t[q1[i]].l].x;
	rep(i,1,tot2) x+=t[t[q2[i]].l].x;
	int mid=(l+r)>>1;
	if(x>=k){
		rep(i,1,tot1) q1[i]=t[q1[i]].l;
		rep(i,1,tot2) q2[i]=t[q2[i]].l;
		return query(l,mid,t[s1].l,t[s2].l,k);
	}
	else{
		rep(i,1,tot1) q1[i]=t[q1[i]].r;
		rep(i,1,tot2) q2[i]=t[q2[i]].r;
		return query(mid+1,r,t[s1].r,t[s2].r,k-x);
	}
}
struct node{
	int op,l,r,k;
}q[maxn];
il void runrk(){
	sort(b+1,b+tot+1);
	sz=unique(b+1,b+tot+1)-(b+1);
	rep(i,1,sz)	rk[b[i]]=i;	
}
int main(){
	sc(T);
	while(T--){
		SC(n,m);
		tot=0,cnt=0,rk.clear();
		rep(i,1,n) sc(a[i]),b[++tot]=a[i];
		char op;
		int l,r,k;
		rep(i,1,m){
			op=getchar();
			while(!(op=='Q' || op=='C')) op=getchar();
			if(op=='Q'){
				SC(l,r),sc(k);
				q[i]=node{1,l,r,k};
			}
			else{
				SC(l,r);
				b[++tot]=r;
				q[i]=node{0,l,r,0};
			}
		}
		runrk();
		root[0]=root[1]=0;
		rep(i,1,n) root1[i]=root[1];
		rep(i,1,n) root[i]=update(1,sz,root[i-1],rk[a[i]],1);
		rep(i,1,m){
			if(q[i].op){ //query
				int x=q[i].l-1,y=q[i].r,k=q[i].k;
				tot1=0,tot2=0;
				while(x){
					q1[++tot1]=root1[x];
					x-=x&-x;
				}
				while(y){
					q2[++tot2]=root1[y];
					y-=y&-y;
				}
				int id=query(1,sz,root[q[i].l-1],root[q[i].r],k);
				printf("%d\n",b[id]);
			}
			else{ // modify
				int x=q[i].l,now=rk[q[i].r],pre=rk[a[x]];
				a[x]=q[i].r;
				while(x<=n){
					root1[x]=update(1,sz,root1[x],pre,-1);
					root1[x]=update(1,sz,root1[x],now,1);
					x+=x&-x; 
				}
			}
		}
		
	}
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值