[provincial election training 2022] simulation match 2

A

Title Description

There are \ (n \) non negative integers within \ ([0,2^w) \), you need to perform the following operations \ (n-1 \) times to minimize the remaining numbers:

  • Select two nonnegative integers \ (x,y \) and combine them into one nonnegative integer \ (Z \), where \ (z=\lfloor\frac{(x|y)}{2}\rfloor \)
  • Select a number \ (x \) to delete it.

\(n\leq 10^5,w\leq 60\)

solution

The first step can be divided into: \ (\ lfloor\frac{(x|y)}{2}\rfloor=\lfloor\frac{x}{2}\rfloor|\lfloor\frac{y}{2}\rfloor \), for problems with complex processes, you can consider guessing the conclusion in the direction of the result, like To make one Similarly to this question, let \ (d_i \) represent the number of times the last \ (I \) number is divided by two, then the final answer can be expressed as \ (\ frac {a_1} {2 ^ {d_1} | \ frac {a_2} {2 ^ {d_2}}... | \ frac {a_n} {2 ^ {d_n} \)

Considering the deletion operation, the necessary and sufficient conditions for a group of \ (\ {d \} \) to be legal are \ (\ sum {I = 1} ^ n \ frac {1} {2 ^ {d}} \ GEQ 1 \)

With this conclusion, let's consider from high to low. Assuming that the digit \ (w \) is considered now, we maintain \ (d_i \) for each number, and then consider changing the \ (w \) bit of the answer to \ (0 \) to see whether it is feasible. Now the answer to be verified is 11010 (0), Because of the or operation, we can't find that the answer is \ (0 \), but the corresponding bit after the number of \ (I \) is shifted to the right \ (d_i \) (we can judge directly by first or then XOR). We want to make \ (d_i \) as small as possible. It's illegal. We increase it step by step.

Time complexity \ (O(nw^2) \), but I'm very dissatisfied, so I can run freely.

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
const int M = 100005;
#define int long long
int read()
{
	int x=0,f=1;char c;
	while((c=getchar())<'0' || c>'9') {if(c=='-') f=-1;}
	while(c>='0' && c<='9') {x=(x<<3)+(x<<1)+(c^48);c=getchar();}
	return x*f;
}
int T,n,w,ans,a[M],d[M],td[M];
void work()
{
	n=read();w=read();
	for(int i=1;i<=n;i++)
		a[i]=read();
	ans=(1ll<<w)-1;
	memset(d,0,sizeof d);
	for(int t=w-1;t>=0;t--)
	{
		int now=ans^(1ll<<t),sum=0;
		for(int i=1;i<=n;i++)
		{
			td[i]=d[i];
			while(((a[i]>>d[i])|now)^now) d[i]++;
			sum+=(1ll<<w-d[i]);
			if(sum>=(1ll<<w)) break; 
		}
		if(sum>=(1ll<<w)) ans=now;
		else memcpy(d,td,sizeof td);
	}
	printf("%lld\n",ans);
}
signed main()
{
	freopen("merge.in","r",stdin);
	freopen("merge.out","w",stdout);
	T=read();
	while(T--) work();
}

B

Title Description

For the string \ (t \), define a line walk and select a positive integer sequence \ (t_1,t_2...t_m \) of any length, where \ (\ forall i\in[1,m],t_i\in [1,|T|],|t_i-t_{i-1}|=1,t_1\not=t_m \) is a palindrome string.

It is good to call a string if and only if each position of the string can be passed at least once through several walks. Now there are \ (q \) times to ask whether it is good to ask a substring \ (s[l_i...r_i] \) each time.

\(n,q\leq 10^6\)

solution

We can find that if there is A small odd palindrome string such as ABA, there must be A solution. This is because accessing all points from one point and then returning to this point can form A palindrome string, but it does not meet the restrictions of different subscripts at the beginning and end. In this case, we can finally go to another A to get the solution.

The problem now is to investigate whether the even palindrome string can cover a complete interval. We consider decomposing this restriction to each position. Let's assume that the nearest symmetric point to the left of a point is \ (l_i \) and the nearest symmetric point to the right is \ (r_i \). I will further explain it with the following figure:

The above figure shows the illegal point \ (I \), so the necessary and sufficient condition that a query cannot be covered by the even palindrome string is \ (\ exist i\in[L,R],[L,R]\subseteq (l_i,r_i) \), in which \ (l_i,r_i \) can be simply preprocessed with the binary hash \ (\) segment tree at the beginning. In particular, if the left side does not cover its symmetry center, then \ (l_i=0 \), If the right side does not cover its center of symmetry, then \ (r_i=n+1 \)

Then the rest is a partial order problem. We consider making scanning lines in the order of the left end points. The scanning process is as follows:

  • Add all \ (l_i < L \) so that we solve a quarter of the partial order relationship.
  • If the right endpoint falls in \ ([I, r_, I) \), it must be illegal, then we mark it illegal in this interval.
  • Finally, we need to solve \ (i\geq L \), so we need to delete the point of \ (I < L \) before querying.

Then the time complexity \ (O(n\log n) \), simple pointer and tree array can be used.

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <set>
using namespace std;
const int M = 1000005;
#define pii pair<int,int>
#define ull unsigned long long
int read()
{
	int x=0,f=1;char c;
	while((c=getchar())<'0' || c>'9') {if(c=='-') f=-1;}
	while(c>='0' && c<='9') {x=(x<<3)+(x<<1)+(c^48);c=getchar();}
	return x*f;
}
int n,m,a[M],b[M],id[M],ans[M],mx[M<<2],mi[M<<2];
ull pw[M],hs[M][2];char s[M];multiset<pii> z;
struct node
{
	int l,r,id;
	bool operator < (const node &b) const
		{return l<b.l;}
}h[M],q[M];
//segment tree
ull check(int l,int r,int op)
{
	if(op==0) return hs[r][0]-hs[l-1][0]*pw[r-l+1];
	return hs[l][1]-hs[r+1][1]*pw[r-l+1];
}
void updmax(int i,int l,int r,int L,int R,int c)
{
	if(L>r || l>R) return ;
	if(L<=l && r<=R) {mx[i]=max(mx[i],c);return ;}
	int mid=(l+r)>>1;
	updmax(i<<1,l,mid,L,R,c);
	updmax(i<<1|1,mid+1,r,L,R,c);
}
void updmin(int i,int l,int r,int L,int R,int c)
{
	if(L>r || l>R) return ;
	if(L<=l && r<=R) {mi[i]=min(mi[i],c);return ;}
	int mid=(l+r)>>1;
	updmin(i<<1,l,mid,L,R,c);
	updmin(i<<1|1,mid+1,r,L,R,c);
}
void dfs(int i,int l,int r)
{
	if(l==r) {id[l]=i;return ;}
	int mid=(l+r)>>1;
	mx[i<<1]=max(mx[i<<1],mx[i]);
	mx[i<<1|1]=max(mx[i<<1|1],mx[i]);
	mi[i<<1]=min(mi[i<<1],mi[i]);
	mi[i<<1|1]=min(mi[i<<1|1],mi[i]);
	dfs(i<<1,l,mid);
	dfs(i<<1|1,mid+1,r);
}
void init()
{
	pw[0]=1;
	for(int i=1;i<=n;i++)
	{
		if(i+2<=n && s[i]==s[i+2]) a[i]++;
		pw[i]=pw[i-1]*371;a[i]+=a[i-1]; 
		hs[i][0]=hs[i-1][0]*371+s[i];
	}
	for(int i=n;i>=1;i--)
		hs[i][1]=hs[i+1][1]*371+s[i];
	for(int i=1;i<=4*n;i++) mi[i]=n+1;
	for(int i=1;i<n;i++)
	{
		int l=1,r=min(i,n-i),len=0;
		while(l<=r)
		{
			int mid=(l+r)>>1;
			if(check(i-mid+1,i,0)==check(i+1,i+mid,1))
				len=mid,l=mid+1;
			else r=mid-1;
		}
		if(len)
			updmax(1,1,n,i+1,i+len,i+1),
			updmin(1,1,n,i-len+1,i,i);
	}
	dfs(1,1,n);
	for(int i=1;i<=n;i++)
	{
		int t1=mx[id[i]],t2=mi[id[i]];
		h[i]=node{!t1?0:2*t1-i-1,t2>n?n+1:2*t2-i+1,i};
	}
}
//tree-array
int lowbit(int x)
{
	return x&(-x);
}
void add(int x,int c)
{
	for(int i=x;i<=n;i+=lowbit(i))
		b[i]+=c;
}
int ask(int x)
{
	int r=0;
	for(int i=x;i>0;i-=lowbit(i))
		r+=b[i];
	return r;
}
signed main()
{
	freopen("pass.in","r",stdin);
	freopen("pass.out","w",stdout);
	n=read();scanf("%s",s+1);
	init();m=read();
	for(int i=1;i<=m;i++)
	{
		q[i].l=read(),q[i].r=read(),q[i].id=i;
		if(q[i].r>2) ans[i]|=(a[q[i].r-2]-a[q[i].l-1]>0);
	}
	sort(h+1,h+1+n);sort(q+1,q+1+m);
	for(int i=1,j=1;i<=m;i++)
	{
		while(j<=n && h[j].l<q[i].l)
		{
			add(h[j].id,1);add(h[j].r,-1);
			z.insert(make_pair(h[j].id,h[j].r));
			j++;
		}
		while(!z.empty() && z.begin()->first<q[i].l)
		{
			pii t=*z.begin();z.erase(z.begin());
			add(t.first,-1);add(t.second,1);
		}
		ans[q[i].id]|=(ask(q[i].r)==0);
	}
	for(int i=1;i<=m;i++)
		putchar(ans[i]+'0');
}

Keywords: string

Added by hofdiggity on Sun, 23 Jan 2022 20:23:02 +0200