Loading

noip模拟22

A. d

通过两个指针分别计数是选择多少个\(a_i\)小的,剩下的删除\(b_i\)小的,队列维护,记得去重.

A_code
#include<bits/stdc++.h>
using namespace std;
namespace BSS
{
	#define p() printf("Pass")
	#define ll long long int
	#define re register ll 
	#define lf double
	#define lb lower_bound 
	#define ub upper_bound 
	#define mp make_pair
	#define File(x,y) freopen(#x,"r",stdin),freopen(#y,"w",stdout)
	#define fill(x,y) memset(x,y,sizeof x);
	#define copy(x,y) memset(y,x,sizeof x);
	#define pass() printf("Pass")
	inline void read(ll &ss)
	{
		ss=0; bool cit=0; char ch;
		while(!isdigit(ch=getchar())) if(ch=='-') cit=1;
		while(isdigit(ch)) ss=(ss<<3)+(ss<<1)+(ch^48),ch=getchar();
		if(cit) ss=-ss;
	}
	inline void write(ll ss)
	{
		static int stas[35]; int topps=0;
  		if(ss<0) putchar('-'),ss=-ss;
  		do{stas[++topps]=ss%10,ss/=10;}while(ss);
  		while(topps) putchar(stas[topps--]+48); puts("");
	}
} using namespace BSS;


const ll N=1e5+50;

ll m,n,ts;
ll vis[N],visb[N];
struct I { ll id,a,b; } f[N],g[N];
inline bool comp1(I i,I j) { return i.a<j.a; }
inline bool comp2(I i,I j) { return i.b<j.b; }
inline void Work()
{
	ll ans=0;
	fill(vis,0); fill(visb,0);
	sort(g+1,g+1+n,comp1);
	sort(f+1,f+1+n,comp2);
//	for(ll i=1;i<=n;i++) cout<<g[i].a<<" ";
//	cout<<endl;
//	for(ll i=1;i<=n;i++) cout<<f[i].b<<" ";
	for(ll i=1;i<=m;i++)
	{
		vis[g[i].id]=1;	
	}
	ll i=1,j=m;
	ll maxa=g[j+1].a;
	while(i<=n and j>=0)
	{
		if(!vis[f[i].id])
		{
			if(visb[g[j].id]) 
			{
				j--;
				continue;
			}
			ans=max(ans,maxa*f[i].b);
			maxa=g[j].a; vis[g[j].id]=0; vis[f[i].id]=1;
			j--; i++; 
		}
		else
		{
			visb[f[i].id]=1;
			i++;
		}
	}
	printf("%lld\n",ans);
	return ;
}
signed main()
{
//	File(0.in,out);
	read(ts);
	while(ts--)
	{
		read(n); read(m);
		for(re i=1;i<=n;i++)
		{
			read(f[i].a); read(f[i].b);
			g[i].a=f[i].a; g[i].b=f[i].b;
			f[i].id=i; g[i].id=i;
		}
		Work();
	}
	return 0;
}

B. e

主席树维护区间.

B_code
#include<bits/stdc++.h>
using namespace std;
namespace BSS {
	#define ll long long int 
	#define ull unsigend ll
	#define re register ll 
	#define lf double
	#define mp(x,y) make_pair(x,y)
	#define lb lower_bound 
	#define ub upper_bound
	#define File(x,y) freopen(#x,"r",stdin),freopen(#y,"w",stdout)
	#define Fill(x,y) memset(x,y,sizeof x)
	#define Copy(x,y) memset(x,y,sizeof x)
	inline ll read() {
		ll ss=0; bool cit=1; char ch;
		while(!isdigit(ch=getchar())) if(ch=='-') cit=0; 
		while(isdigit(ch)) ss=(ss<<3)+(ss<<1)+(ch^48),ch=getchar();
		return cit?ss:-ss;
	}
} using namespace BSS;

const ll N=1e6+55;
ll m,n,ts,tot,cnt,type,alls,lst,z;
ll head[N],val[N],dep[N],fa[N],siz[N],dfn[N],top[N],son[N],rk[N],rt[N];
ll num[N*3],r[N*3],lsh[N*3],id[N*3];
struct I { ll u,v,nxt; } e[N<<1];
struct II { ll ls,rs,sum; } tr[N<<3];
inline ll inc(ll i,ll j){ i+=j; return i>=n ? (i-=n) : i ; }
inline ll dec(ll i,ll j) { i-=j; return i<=0 ? i=(i+n*n)%n : i ; }
inline void add(ll u,ll v){
	e[++ts].u=u;
	e[ts].v=v;
	e[ts].nxt=head[u];
	head[u]=ts;
}
inline ll clone(ll pre){
	tr[++z]=tr[pre];
	return z;
}
inline void pushup(ll x){
	tr[x].sum=tr[tr[x].ls].sum+tr[tr[x].rs].sum;
	return ;
}
void transit(ll &x,ll pre,ll l,ll r,ll pos){
	x=clone(pre);
	if(l==r){
		tr[x].sum++;
		return ;
	}
	ll mid=(l+r)>>1;
	if(pos<=mid) transit(tr[x].ls,tr[pre].ls,l,mid,pos);
	else transit(tr[x].rs,tr[pre].rs,mid+1,r,pos);
	pushup(x);
	return ;
}
void dfs1(ll now,ll dad,ll depth){
	fa[now]=dad, dep[now]=depth,
	siz[now]=1, val[now]=lb(lsh+1,lsh+1+cnt,val[now])-lsh;
	transit(rt[now],rt[dad],1,cnt,val[now]);
	for(re i=head[now];i;i=e[i].nxt){
		if(e[i].v==dad) continue;
		dfs1(e[i].v,now,depth+1);
		siz[now]+=siz[e[i].v];
		if(siz[son[now]]<siz[e[i].v]){
			son[now]=e[i].v;
		}
	}
	return ;
}
void dfs2(ll now,ll high){
	dfn[now]=++tot, rk[tot]=now, top[now]=high;
	if(!son[now]) return ;
	dfs2(son[now],high);
	for(re i=head[now];i;i=e[i].nxt){
		if(e[i].v==fa[now] or e[i].v==son[now]) continue;
		dfs2(e[i].v,e[i].v);
	}
	return ;
}
ll query_pre(ll x,ll pre,ll l,ll r,ll pos){
	if(l==r){
		return l;
	}
	ll mid=(l+r)>>1; ll temp;
	if(tr[tr[x].rs].sum-tr[tr[pre].rs].sum<=0) 
		return query_pre(tr[x].ls,tr[pre].ls,l,mid,pos);
	else{	
		if(tr[tr[x].ls].sum-tr[tr[pre].ls].sum<=0) 
			return query_pre(tr[x].rs,tr[pre].rs,mid+1,r,pos);
	}
	if(pos<=mid) return query_pre(tr[x].ls,tr[pre].ls,l,mid,pos);
	else{
		temp=query_pre(tr[x].rs,tr[pre].rs,mid+1,r,pos);
		if(temp>pos) return query_pre(tr[x].ls,tr[pre].ls,l,mid,pos);
		else return temp;
	}
}
ll query_suf(ll x,ll pre,ll l,ll r,ll pos){
	if(l==r){
		return l;
	}
	ll mid=(l+r)>>1; ll temp;
	if(tr[tr[x].rs].sum-tr[tr[pre].rs].sum<=0) 
		return query_suf(tr[x].ls,tr[pre].ls,l,mid,pos);
	else{	
		if(tr[tr[x].ls].sum-tr[tr[pre].ls].sum<=0) 
			return query_suf(tr[x].rs,tr[pre].rs,mid+1,r,pos);
	}
	if(pos>=mid+1) return query_suf(tr[x].rs,tr[pre].rs,mid+1,r,pos);
	else{
		temp=query_suf(tr[x].ls,tr[pre].ls,l,mid,pos);
		if(temp<pos) return query_suf(tr[x].rs,tr[pre].rs,mid+1,r,pos);
		else return temp;
	}
}
inline ll lca(ll x,ll y){
	while(top[x]!=top[y]){
		if(dep[top[x]]<dep[top[y]]) swap(x,y);
		x=fa[top[x]];
	}
	if(dep[x]>dep[y]) swap(x,y);
	return x;
}
signed main(){
//	File(0.in,out);
	n=read(); m=read(); type=read();
	ll u,v,w;
	for(re i=1;i<=n;i++) lsh[++cnt]=val[i]=read();
	for(re i=2;i<=n;i++){
		u=read(); v=read();
		add(u,v); add(v,u);
	}
	for(re i=1;i<=m;i++){
		lsh[++cnt]=r[i]=read(),num[i]=read();
		for(re j=1;j<=num[i];j++){
			id[++alls]=read();
		}
	}
	sort(lsh+1,lsh+1+cnt); cnt=unique(lsh+1,lsh+1+cnt)-lsh-1;
	dfs1(1,0,1); dfs2(1,1); alls=0; lst=0; ll temp,anor,ans1,ans2,ans;
	for(re i=1;i<=m;i++){
		r[i]=lb(lsh+1,lsh+1+cnt,r[i])-lsh; ++alls;
		id[alls]=inc(id[alls]-1,(lst*type)%n)+1;
		anor=id[alls]; ans=1e10;
		for(re j=2;j<=num[i];j++){
			++alls;
			id[alls]=inc(id[alls]-1,(lst*type)%n)+1,
			anor=lca(id[alls],anor); 
		}
		for(re j=0;j<num[i];j++){
			temp=alls-j;
			ans1=query_pre(rt[id[temp]],rt[fa[anor]],1,cnt,r[i]);
			ans1=abs(lsh[r[i]]-lsh[ans1]),
			ans2=query_suf(rt[id[temp]],rt[fa[anor]],1,cnt,r[i]);
			ans2=abs(lsh[r[i]]-lsh[ans2]);
			ans=min(ans,min(ans1,ans2));
		}
		lst=ans;
		printf("%lld\n",ans);
	}
	return 0;
}

C. f

考场上发现每一位对于答案都是独立的,且根据位的先后具有优先性.
发现答案具有单调性,于是选择二分答案.
考虑 \(Meet\ in\ the\ Middle\) 从而对指数进行优化.

C_code
#include<bits/stdc++.h>
using namespace std;
namespace BSS
{
	#define ll long long int
	#define ull unsigned ll
	#define re register ll 
	#define lf double
	#define mp make_pair
	#define File(x,y) freopen(#x,"r",stdin),freopen(#y,"w",stdout)
	#define fill(x,y) memset(x,y,sizeof x);
	#define copy(x,y) memset(y,x,sizeof x);
	inline void read(ll &ss)
	{
		ss=0; bool cit=0; char ch;
		while(!isdigit(ch=getchar())) if(ch=='-') cit=1;
		while(isdigit(ch)) ss=(ss<<3)+(ss<<1)+(ch^48),ch=getchar();
		if(cit) ss=-ss;
	}
	inline void write(ll ss)
	{
		static int stas[35]; int topps=0;
  		if(ss<0) putchar('-'),ss=-ss;
  		do{stas[++topps]=ss%10,ss/=10;}while(ss);
  		while(topps) putchar(stas[topps--]+48); puts("");
	}
} using namespace BSS;


const ll N=5e5+50;
ll m,n,rk,tot,ans;
ll a[N],b[N],val[N];
ll sum0[50],sum1[50];// sum0 为异或之前的逆序对个数
struct I { ll cnt,siz,son[2]; } tr[N*64]; // 逆序对个数,子树大小
//inline bool comp(I i,I j) { return i.w==j.w ? i.id<j.id ? i.w>j.w ; }
pair<ll,ll> f1[1<<16],f2[1<<16];
ll que[1<<16];
void Insert(ll now)
{
	ll p=0;
	for(ll i=30;i>=-1;i--)
	{
		tr[p].siz++;
		if(i==-1) break;
		if((now>>i)&1)
		{
			if(tr[p].son[0]) sum1[i]+=tr[tr[p].son[0]].siz;
			if(tr[p].son[1]) p=tr[p].son[1];
			else tr[p].son[1]=++tot,p=tot;
		}
		else
		{
			if(tr[p].son[1]) sum0[i]+=tr[tr[p].son[1]].siz; 
			if(tr[p].son[0]) p=tr[p].son[0];
			else tr[p].son[0]=++tot,p=tot;
		}
	}
	return ;
}
inline bool check(ll x)
{	
	ll temp=0;
	ll j=(1<<(m-m/2))-1;
	for(ll i=0;i<(1<<m/2) and f1[i].first<=x;i++)
	{
		while(f1[i].first+f2[j-1].first>=x and j>=0)
		{
			j--;
		}
		temp+=j;
	}
	if(temp>=rk) return 0;
	else return 1;
	//如果逆序对个数比 x 小的状态种类数大于 rk,那么就让 x 变小
}
inline ll getans()
{
	ll temp=0; ll j=(1<<(m-m/2))-1;
	ll cnt=0; fill(que,0);
	for(ll i=0;i<(1<<m/2) and f1[i].first<=ans;i++)
	{
		while(f1[i].first+f2[j-1].first>ans and j>=0)
		{
			j--;
		}
		temp+=j;
		if(f1[i].first+f2[j-1].first==ans)
		{
			que[++cnt]=f2[j-1].second<<(m/2)|f1[i].second;
		}
	}
	sort(que+1,que+1+cnt);
	for(ll i=temp;i>=0 and cnt>=0;i--,cnt--)
	{
		if(i==rk)
		{
			return que[cnt];
		}
	}
	return 0;
}
signed main()
{
//	File(0.in,out);
	read(n); read(m); read(rk);
	if(m==0) 
	{
		printf("0 0");
		return 0;
	}
	for(ll i=1;i<=n;i++)
	{
		read(val[i]);
		Insert(val[i]);
	}
	for(ll i=0;i<(1<<m/2);i++)
	{
		for(ll j=0;j<m/2;j++)
		{
			if((i>>j)&1) f1[i].first+=sum1[j];
			else f1[i].first+=sum0[j];
		}
		f1[i].second=i;
	}
	for(ll i=0;i<(1<<(m-m/2));i++)
	{
		for(ll j=0;j<=m-m/2;j++)
		{
			if((i>>j)&1) f2[i].first+=sum1[j+m/2];
			else f2[i].first+=sum0[j+m/2];
		}
		f2[i].second=i;
	}
	sort(f1,f1+(1<<m/2));
	sort(f2,f2+(1<<(m-m/2)));
	ll le=0,ri=(n-1)*n/2,mid;
	// 二分逆序对个数
	// 求出排名为 rk 的逆序对究竟有多少个
	while(le<=ri)
	{
		mid=(le+ri)>>1;
		if(check(mid)) le=mid+1;
		else ri=mid-1;
	}
	ans=ri;
	printf("%lld %lld",ans,getans());
	return 0;
}
posted @ 2021-08-05 19:57  AaMuXiiiiii  阅读(27)  评论(0编辑  收藏  举报