模拟赛D2

T 1 T1

观察一下 A 1 A 1...1 A A1A1...1A .

我们可以贪心从 A A 的左端点跳到前一个 A A 的左端点,复杂度 O ( n ln n ) O(n\ln n) .

#include<cstdio>
#include<algorithm>
#define mk make_pair
using namespace std;
const int N=5e5+10;
int n,id[N],pre[N],s[N],m;
char ch[N]; pair<int,int> ans;

int main() {
	scanf("%d%s",&n,ch+1);
	for(int i=1,x=0,y=0;i<=n;i++)
		if(ch[i]=='0') pre[i]=y,x=i,s[++m]=i,id[i]=m;
		else pre[i]=x,y=i;
	ans=mk(n-m,0);
	for(int i=1;i<=m;i++) {
		int x=s[m-i+1],y=i;
		while(id[pre[pre[x]]]>=i) {
			y+=i+1;
			x=s[id[pre[pre[x]]]-i+1];
		}
		if(y>i) ans=max(ans,mk(y,i));
		else break;
	}
	int a=ans.first,b=ans.second;printf("%d\n",a);
	while(a) {
		for(int i=1;i<=b;i++) putchar('0');
		a-=b; if(a) putchar('1'),a--;
	}
	return 0;
}

T 2 T2

线段树.

我们在规定直线上跑最短路.

若两点都未被直线覆盖则不合法.

若一行一列覆盖两点,那么曼哈顿距离则为答案.

否则,都被行/列覆盖.我们下面只讲行的情况.

若中间有列或中间的行都被覆盖则为曼哈顿距离.

否则,往左/右走一段,再折回来.

#include<bits/stdc++.h>
#define gc getchar()
using namespace std;
const int N=1e6+10;

template<class o> void qr(o&x) {
	char c=gc; x=0; int f=1;
	while(!isdigit(c)) {if(c=='-') f=-1; c=gc;}
	while(isdigit(c))x=x*10+c-'0',c=gc;
	x*=f;
}

template<class o> void qw(o x) {
	if(x<0) putchar('-'),x=-x;
	if(x/10) qw(x/10);
	putchar(x%10+'0');
}

template<class o> void pr2(o x) {qw(x); puts("");}

int n,m,q,now,row[N],col[N];

struct ST {
	int mx[N<<2],mn[N<<2];
	#define lc (x<<1)
	#define rc (x<<1|1)
	void add(int x,int l,int r,int pos) {
		mx[x]=now;
		if(l==r) {mn[x]=now; return ;}
		int mid=(l+r)/2;
		if(pos<=mid) add(lc,l,mid,pos);
		else 	     add(rc,mid+1,r,pos);
		mn[x]=min(mn[lc],mn[rc]);
	}
	int Max(int x,int l,int r,int L,int R) {
		if(L<=l&&r<=R) return mx[x];
		int mid=(l+r)/2,t=0;
		if(L<=mid) t=Max(lc,l,mid,L,R);
		if(mid< R) t=max(t,Max(rc,mid+1,r,L,R));
		return t;
	}
	int Min(int x,int l,int r,int L,int R) {
		if(L<=l&&r<=R) return mn[x];
		int mid=(l+r)/2,t=N;
		if(L<=mid) t=Min(lc,l,mid,L,R);
		if(mid< R) t=min(t,Min(rc,mid+1,r,L,R));
		return t;
	}
	int solvel(int x,int l,int r,int p,int v) {
		if(l>=p||mx[x]<v) return 0;
		if(l==r) return l;
		int mid=(l+r)/2,t=solvel(rc,mid+1,r,p,v);
		if(!t) t=solvel(lc,l,mid,p,v);
		return t;
	}
	int solver(int x,int l,int r,int p,int v) {
		if(r<=p||mx[x]<v) return 0;
		if(l==r) return l;
		int mid=(l+r)/2,t=solver(lc,l,mid,p,v);
		if(!t) t=solver(rc,mid+1,r,p,v);
		return t;
	}
} r,c;

int solve(int x1,int y1,int x2,int y2,int v) {
	int a=(row[x1]>=v)|((col[y1]>=v)*2),b=(row[x2]>=v)|((col[y2]>=v)*2);
	if(!a||!b) return -1;
	if(x1>x2) swap(x1,x2);
	if(y1>y2) swap(y1,y2);
	int ans=x2-x1+y2-y1,tmp,ad=N;
	if((a|b)==3) return ans;
	if((a&b)==1) {
		if(r.Min(1,1,n,x1,x2)>=v||c.Max(1,1,m,y1,y2)>=v) return ans;
		if(tmp=c.solvel(1,1,m,y1,v)) ad=min(ad,y1-tmp);
		if(tmp=c.solver(1,1,m,y2,v)) ad=min(ad,tmp-y2);
		if(ad==N) return -1;
		ans+=ad*2;
	}
	else {
		if(c.Min(1,1,m,y1,y2)>=v||r.Max(1,1,n,x1,x2)>=v) return ans;
		if(tmp=r.solvel(1,1,n,x1,v)) ad=min(ad,x1-tmp);
		if(tmp=r.solver(1,1,n,x2,v)) ad=min(ad,tmp-x2);
		if(ad==N) return -1;
		ans+=ad*2;
	}
	return ans;
}

int main() {
	qr(n); qr(m); qr(q);
	for(int i=1,op,x1,y1,x2,y2,v;i<=q;i++) {
		qr(op); qr(x1); now=i;
		if(op==1) row[x1]=i,r.add(1,1,n,x1);
		else if(op==2) col[x1]=i,c.add(1,1,m,x1);
		else {
			qr(y1); qr(x2); qr(y2); qr(v);
			pr2(solve(x1,y1,x2,y2,i-v));
		}
	}
	return 0;
}

T 3 T3

一开始想了用树状数组求 mex \text{mex} .但是显然会T.

考虑优化,假设当前的所有点都未删去,我们求得的 m e x mex 值为 t t .

如果删去的数为 x x ,则答案为 min ( x , t ) \min(x,t) .

所以用单调队列维护一下删除数即可.

#include<bits/stdc++.h>
#define lc (x<<1)
#define rc (x<<1|1)
#define gc getchar()//(p1==p2&&(p2=(p1=buf)+fread(buf,1,size,stdin),p1==p2)?EOF:*p1++)
#define mk make_pair
#define pi pair<int,int>
#define pb push_back
#define IT iterator
#define fi first
#define se second
#define vi vector<int>
#define SZ(a) ((int)a.size())
#define all(a) a.begin(),a.end()
using namespace std;
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
const int N=2e6+10,size=1<<20;

//char buf[size],*p1=buf,*p2=buf;
template<class o> void qr(o &x) {
	char c=gc; x=0; int f=1;
	while(!isdigit(c)){if(c=='-')f=-1; c=gc;}
	while(isdigit(c)) x=x*10+c-'0',c=gc;
	x*=f;
}
template<class o> void qw(o x) {
	if(x/10) qw(x/10);
	putchar(x%10+'0');
}
template<class o> void pr1(o x) {
	if(x<0)x=-x,putchar('-');
	qw(x); putchar(' ');
}
template<class o> void pr2(o x) {
	if(x<0)x=-x,putchar('-');
	qw(x); puts("");
}


namespace IO{
	int c;
	unsigned int seed;
	unsigned int randnum(){
		seed^=seed<<13;
		seed^=seed>>17;
		seed^=seed<<5;
		return seed;
	}

	inline int read(int &x){scanf("%d",&x);return x;}
	inline void init_case(int &m,int &a,int &b,int &d,int p[]){
		scanf("%d%u%d%d%d%d",&m,&seed,&a,&b,&c,&d);
		for(int i=1;i<=m;i++){
			if(randnum()%c==0)p[i]=-1;
			else p[i]=randnum()%b;
		}
	}

	inline void update_ans(unsigned int &ans_sum,unsigned int cur_ans,int no){
		const static unsigned int mod=998244353;
		ans_sum^=(long long)no*(no+7)%mod*cur_ans%mod;
	}
}
using IO::read;
using IO::init_case;
using IO::update_ans;

bool buy[N],vis[N];
int q[N],l,r;//丢失
int T,m,a,b,d;

int c[N],lg,cnt;

namespace Q {
	int q[N],l,r;
	void init(){l=1; r=0;}
	void push(int x) {
		while(l<=r&&q[r]>x) r--;
		q[++r]=x;
	}
	void del(int x) {
		if(l<=r&&q[l]==x) l++;
	}
	int front() {return l<=r?q[l]:N;}
} 

int ask() {
	while(buy[cnt+1]) cnt++;
	return min(cnt,Q::front());
}

int main(){
//	freopen("c.in","r",stdin);
//	freopen("c.out","w",stdout);
	static int p[2000005];
	read(T); 
	while(T--) {
		Q::init();
		unsigned int ans_sum=0,cur_ans=0;
		memset(c+1,0,sizeof(int[b]));
		memset(buy+1,0,sizeof(bool[b+1]));
		memset(vis+1,0,sizeof(bool[b+1]));//树状数组无0,所以整体+1 
		init_case(m,a,b,d,p); b++; cnt=a+1;
		for(lg=1;(1<<(lg+1))<=b;lg++);
		for(int i=0;i<=a;i++) 
			buy[i+1]=vis[i+1]=1;
		l=1; r=0;
		for(int i=1;i<=m;i++) {
			cur_ans=0;
			int x=p[i];
			if(x==-1) {
				if(!d&&l<=r) {
					x=q[l++];
					Q::del(x-1);
					vis[x]=1;
					cur_ans=ask();
				}
			}
			else {
				++x;
				if(!buy[x]) {
					buy[x]=vis[x]=1;
					cur_ans=ask();
				}
				else if(!d) {
					if(vis[x]) {
						vis[x]=0;
						q[++r]=x;
						Q::push(x-1);
						cur_ans=ask();
					}
					else if(l<=r) {
						x=q[l++];
						vis[x]=1;
						Q::del(x-1);
						cur_ans=ask();
					}
				}
			}
			update_ans(ans_sum,cur_ans,i);
		}
		printf("%u\n",ans_sum);
	}
	return 0;
}


猜你喜欢

转载自blog.csdn.net/qq_42886072/article/details/106668053
d2