The wrong rehabilitation training-CF1329B & C: Heap Sequences

CF1329B Dreamoon Likes Sequences

Title description

A sequence is eligible if and only if the sequence is non-empty and monotonically increased and the prefix XOR and monotonically increased.
Given \ (d, m \) ( \ (d, m \ leq 10 ^ 9 \) ), ask all of the numbers in the sequence that each number is a positive integer not exceeding \ (d \) . What is the number modulus \ (m \) .

answer

Assume that the length of a legal sequence is \ (n \) , the sequence is \ (a_1, a_2, ..., a_n \) , and the prefix sum is \ (b_1, b_2, ..., b_n \) .
If you want to increase \ (\ {b_n \} \) , you must have \ (\ forall i, b_i <b_ {i + 1} \) .
\ (b_i <b_ {i + 1} \) There are two cases: 1. The highest binary bit of \ (b_ {i + 1} \) is higher than \ (b_i \) ; 2. The highest binary bit of both The same, and after subtracting the highest bit of both, \ (b_ {i + 1} \) is larger.
Consider the second case, both found that if the highest bit the same, by the \ (a_ {i + 1} = b_i \ space xor \ space b_ {i + 1} \) available \ (a_ {i + 1} \ ) Has the highest bit lower than \ (b_i \) , and the highest bit of at least one of \ (a_1, ..., a_i \) is the same as \ (b_i \) . The conditions for single increase do not match.
So there is no second situation. In other words, \ (\ {b_n \} \)The highest binary bit of each number in is higher than the previous number.
It can be concluded that the highest binary digit of each number in \ (\ {a_n \} \) is higher than the previous number.
The \ (1,2, ..., d \ ) numbers classified according to the highest bits. You can choose one or not in each category.

Code

#include<algorithm>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<iomanip>
#include<iostream>
#include<map>
#include<queue>
#include<stack>
#include<vector>
#define LL long long
#define rep(i,x,y) for(int i=(x);i<=(y);++i)
#define dwn(i,x,y) for(int i=(x);i>=(y);--i)
#define view(u,k) for(int k=fir[u];~k;k=nxt[k])
using namespace std;
int read()
{
	int x=0,f=1;char ch=getchar();
	while(!isdigit(ch)&&ch!='-')ch=getchar();
	if(ch=='-')f=-1,ch=getchar();
	while(isdigit(ch))x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
	return x*f;
}
void write(int x)
{
	char ch[20];int f=0;
	if(!x){putchar('0'),putchar('\n');return;}
	if(x<0)putchar('-'),x=-x;
	while(x)ch[++f]=x%10+'0',x/=10;
	while(f)putchar(ch[f--]);
	putchar('\n');
}
int t,d,m,ans;
int mo(int x){if(x>=m)return x-m;if(x<0)return x+m;return x;}
int main()
{
	t=read();
	while(t--)
	{
		d=read(),m=read();ans=1;
		LL now=1,nxt=1;
		while(1)
		{
			if(nxt>=d){ans=(LL)ans*(d-now+2)%m;break;}
			ans=(LL)ans*(nxt-now+2)%m,now=nxt+1;nxt=(now<<1)-1;
		}
		ans=mo(ans-1);
		write(ans);
	}
	return (~(0-0)+1);
}

CF1329C Drazil Likes Heap

Title description

There is a somewhat weighted full binary tree with a height of \ (h \) , which satisfies the nature of large root heaps.
Delete a point that is not a leaf. The son with a larger weight will move to the position of the point, and then repeat the process at the original position of the son.
To delete some points, make it into a full binary tree with a height of \ (g \) , and the point weight of the remaining points is as small as possible. Ask the minimum point weight and which points to delete.
All points have different point weights, \ (g \ leq h \ leq 20 \) .

answer

Firstly, it is found that the point weights of the remaining parts have nothing to do with the order of deleting points, because the point weights of each point will become the maximum value of the atomic tree after deletion.
Consider a greedy construction method: construct from bottom to top, so that the new point weight of each point is the smallest possible point weight in the atomic tree that is greater than the new point weights of the sons around the point.
The selection of the point weight as small as possible will not make the lower bound of the ancestor of the point larger.
It is possible to maintain a sub-tree point weight array in order of size at each point. An array of points can be merged by the array of left and right sons in a similar sorting method. Time complexity \ (\ Theta (2 ^ h \ times h) \) .
If you use all the sons who traverse the point every time to find its point weight, the time complexity is also \ (\ Theta (2 ^ h \ times h) \) , but the recursive constant is slightly larger.

There is another completely intuitive greedy approach to this problem: delete the value at the current root until the distance from the closest leaf to the root is \ (g \) , and then process the left and right subtrees recursively.
Because the maximum value is at the top of the heap, and when a point and all its ancestors cannot be deleted, there is no effect between its left and right subtrees. The time complexity is also \ (\ Theta (2 ^ h \ times h) \)

Code

#include<algorithm>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<iomanip>
#include<iostream>
#include<map>
#include<queue>
#include<stack>
#include<vector>
#define LL long long
#define rep(i,x,y) for(int i=(x);i<=(y);++i)
#define dwn(i,x,y) for(int i=(x);i>=(y);--i)
#define view(u,k) for(int k=fir[u];~k;k=nxt[k])
using namespace std;
#define maxn ((1<<20)+7)
#define pii pair<int,int>
#define fi first
#define se second
#define mp make_pair
#define ls (u<<1)
#define rs (u<<1|1)
int read()
{
	int x=0,f=1;char ch=getchar();
	while(!isdigit(ch)&&ch!='-')ch=getchar();
	if(ch=='-')f=-1,ch=getchar();
	while(isdigit(ch))x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
	return x*f;
}
void write(LL x)
{
	char ch[20];int f=0;
	if(!x){putchar('0'),putchar('\n');return;}
	if(x<0)putchar('-'),x=-x;
	while(x)ch[++f]=x%10+'0',x/=10;
	while(f)putchar(ch[f--]);
	putchar('\n');
}
int t,n,h,g,a[maxn],yes[maxn],len,dfn[maxn],siz[maxn],val[maxn];
LL ans;
pii ar[maxn],tmp[maxn];
void merge(int u)
{
	int nl=dfn[ls],nr=dfn[rs],c=0;
	rep(i,1,siz[u])
	{
		int va=(nl>=dfn[ls]+siz[ls]?1e9:ar[nl].fi),
		vb=(nr>=dfn[rs]+siz[rs]?1e9:ar[nr].fi),
		vc=c?1e9:a[u];
		if(va<min(vb,vc)){tmp[i].fi=va,tmp[i].se=ar[nl].se,nl++;}
		else if(vb<min(va,vc)){tmp[i].fi=vb,tmp[i].se=ar[nr].se,nr++;}
		else tmp[i].fi=a[u],tmp[i].se=u,c++;
	}
	rep(i,1,siz[u])ar[dfn[u]+i-1]=tmp[i];
}
int getv(int u,int li)
{
	int L=dfn[u],R=dfn[u]+siz[u]-1;pii res;res.fi=1e9;
	while(L<=R)
	{
		int mid=(L+R>>1);
		if(ar[mid].fi>li)
		{
			if(res.fi>ar[mid].fi)res=ar[mid];
			R=mid-1;	
		}
		else L=mid+1;
	}
	yes[res.se]=1;
	return res.fi;
}
void work(int u,int d)
{
	if(d==g)
	{
		sort(ar+dfn[u],ar+dfn[u]+siz[u]);
		val[u]=ar[dfn[u]].fi,yes[ar[dfn[u]].se]=1,ans+=val[u];
		return;
	}
	work(ls,d+1),work(rs,d+1),merge(u);
	val[u]=getv(u,max(val[ls],val[rs])),ans+=val[u];
	return;
}
void build(int u,int d)
{
	dfn[u]=++len,ar[len].fi=a[u],ar[len].se=u,siz[u]=1;
	if(d==h){return;}
	build(ls,d+1),build(rs,d+1),siz[u]+=siz[ls]+siz[rs];
	return;
}
int main()
{
	t=read();
	while(t--)
	{
		h=read(),g=read(),n=(1<<h)-1;ans=len=0;
		rep(i,1,n)a[i]=read(),yes[i]=0;
		build(1,1);
		work(1,1);
		write(ans);
		dwn(i,n,1)if(!yes[i])printf("%d ",i);
		puts("");
	}
	return (~(0-0)+1);
}

Some thoughts

Don't be black when you cross the line of fire: Teaming up with someone who crosses the line of fire cannot improve the level, and teaming with someone who is not so strong cannot increase the score.
However, hacking with people with strong English can improve both the level (referring to having more time to think before falling asleep instead of translating) and improving the score (referring to having more time to think about the question, which is easier to score). :)

Guess you like

Origin www.cnblogs.com/xzyf/p/12664515.html