21杭电多校第九场

A

先构造出\(1-8,16\)\(9\)个数,共需要\(17\)

之后按照每四位一个单位构造数\(x\),若\(x\)的末四位\(\le 8\)可以直接加,否则需要在之前\(+1\)然后减去一个\(<8\)的数

这样每一个\(4\)位最多用两步即可解决,一共最多\(17+16\times2+1=50\)

(注意一直进位使得整个数多一位的情况下,中间会有一些\(0\),这些\(0\)节约了步数,使得总步数仍满足要求

#include<bits/stdc++.h>
#define inf 2139062143
#define ll long long
#define db double
#define ld long double
#define ull unsigned long long
#define MAXN 100100
#define MOD 998244353
#define Fill(a,x) memset(a,x,sizeof(a))
#define rep(i,s,t) for(int i=(s),i##end=(t);i<=i##end;++i)
#define dwn(i,s,t) for(int i=(s),i##end=(t);i>=i##end;--i)
#define ren for(int i=fst[x];i;i=nxt[i])
#define pls(a,b) (a+b)%MOD
#define mns(a,b) (a-(b))%MOD
#define mul(a,b) (1LL*(a)*(b))%MOD
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
using namespace std;
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
void solve(ull x)
{
	if(x<16)
	{
		if(x<=8)
		{
			puts("p1");x--;
			if(x) printf("add %d\n",10-x);
		}
		else printf("dup\nsub %d\n",10-(16-x));
		return ;
	}
	ull now=x&15;
	if(now<=8)
	{
		solve(x>>4);puts("mul 1");
		if(now) printf("add %d\n",10-now);
	}
	else
	{
		solve((x>>4)+1);puts("mul 1");
		printf("sub %d\n",10-(16-now));
	}
}
int main()
{
	ull n;rep(T,1,read())
	{
		cin>>n;
		if(!n) {puts("p1\nsub 0\nend");continue;}
		puts("p1");rep(i,1,7) printf("dup\nadd %d\n",i);
		puts("dup\nmul 7");solve(n);puts("end");
	}
}

B

显然只有在开始时结束游戏这一操作才有意义,否则继续游戏总是更优

考虑一下游戏由谁结尾,若\(k\)为奇数即\(A\)结尾,则\(B\)应选择该行\(max\)最小的行

同理,由\(B\)结尾则\(A\)应选择\(min\)最大的列

特判一下\(k=1\)\(A\)直接结束游戏的情况即可

#include<bits/stdc++.h>
#define inf 2139062143
#define ll long long
#define db double
#define ld long double
#define ull unsigned long long
#define MAXN 100100
#define MOD 998244353
#define Fill(a,x) memset(a,x,sizeof(a))
#define rep(i,s,t) for(int i=(s),i##end=(t);i<=i##end;++i)
#define dwn(i,s,t) for(int i=(s),i##end=(t);i>=i##end;--i)
#define ren for(int i=fst[x];i;i=nxt[i])
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
using namespace std;
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
namespace CALC
{
	inline int pls(int a,int b){return a+b>=MOD?a+b-MOD:(a+b<0?a+b+MOD:a+b);}
	inline int mns(int a,int b){return a-b<0?a-b+MOD:(a-b>=MOD?a-b-MOD:a-b);}
	inline int mul(int a,int b){return (1LL*a*b)%MOD;}
	inline void inc(int &a,int b){a=pls(a,b);}
	inline void dec(int &a,int b){a=mns(a,b);}
	inline void tms(int &a,int b){a=mul(a,b);}
	inline int qp(int x,int t,int res=1)
		{for(;t;t>>=1,x=mul(x,x)) if(t&1) res=mul(res,x);return res;}
	inline int Inv(int x){return qp(x,MOD-2);}
}
using namespace CALC;
int n,m,k,g[MAXN],mx[MAXN],mn[MAXN],ans;
int main()
{
	rep(T,1,read())
	{
		n=read(),m=read(),k=read();
		rep(i,1,n*m) g[i]=read();
		rep(i,1,n) {mx[i]=0;rep(j,1,m) mx[i]=max(mx[i],g[i*m-m+j]);}
		rep(j,1,m) {mn[j]=inf;rep(i,1,n) mn[j]=min(mn[j],g[i*m-m+j]);}
		if(k==1) ans=mx[1];
		else if(k&1)
		{
			ans=inf;rep(i,1,n) ans=min(ans,mx[i]);
			ans=max(ans,g[1]);
		}
		else 
		{
			ans=0;rep(j,1,m) ans=max(ans,mn[j]);
			ans=max(ans,g[1]); 
		}
		printf("%d\n",ans);
	}
}

C

对于一个数\(x\)的最大排名来说,需要找到最大的\(k\)满足较大的\(k\)\(a_i\)与较大的\(k\)\(b_i\)反向相加均大于\(a_x+b_n\)

因此需要对每一个\(a_i\)求出最小的\(b_j\)使\(a_i+b_j>a_x+b_n\),将\(a\)排序后由单调性可以通过简单求出

求出的所有\(b\)相当于一些限制,找到均满足这些限制的最大\(k\)即可

最小排名同理

#include<bits/stdc++.h>
#define inf 2139062143
#define ll long long
#define db double
#define ld long double
#define ull unsigned long long
#define MAXN 100100
#define MOD 998244353
#define Fill(a,x) memset(a,x,sizeof(a))
#define rep(i,s,t) for(int i=(s),i##end=(t);i<=i##end;++i)
#define dwn(i,s,t) for(int i=(s),i##end=(t);i>=i##end;--i)
#define ren for(int i=fst[x];i;i=nxt[i])
#define pls(a,b) (a+b)%MOD
#define mns(a,b) (a-(b))%MOD
#define mul(a,b) (1LL*(a)*(b))%MOD
#define pii pair<int,int>
#define w first
#define id second
#define pb push_back
using namespace std;
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
int n,mn[MAXN],mx[MAXN],b[MAXN];
pii g[MAXN];
int main()
{
	int pos,res,cnt;rep(T,1,read())
	{
		n=read();rep(i,1,n) g[i]={read(),i};
		rep(i,1,n) b[i]=read();
		sort(g+1,g+n+1);
		rep(i,1,n) 
		{
			pos=n-1,res=n-1,cnt=0;dwn(j,n,1) if(i!=j)
			{
				cnt++;
				while(g[j].w+b[pos]<=g[i].w+b[n]&&pos) pos--;
				res=min(res,cnt+pos-1);
			}
			mx[g[i].id]=res+1;
		}
		rep(i,1,n>>1) swap(b[i],b[n+1-i]);
		rep(i,1,n)
		{
			pos=n-1,res=n-1,cnt=0;rep(j,1,n) if(i!=j)
			{
				cnt++;
				while(g[j].w+b[pos]>g[i].w+b[n]&&pos) pos--;
				res=min(res,cnt+pos-1);
			}
			mn[g[i].id]=n-res;
		}
		rep(i,1,n) printf("%d %d\n",mn[i],mx[i]);
	}
}

D

看上去是个推式子概率题 咕

E

显然每次选择手牌应当和丢弃手牌都应贪心地选择\(d\)较大的,才能满足求最坏情况下的最大值这个要求

由于丢弃手牌数\(\le 4\),考虑将所有手牌按照\(a_i\)分类,每一类中按照\(d_i\)升序排序

\(f[a][b][c][d][k]\)表示当前四种牌分别剩\(a,b,c,d\)

\(k=0\)表示当前需要选择有贡献的手牌 转移为在四种牌堆顶中取一个后舍弃\(a_i\)个 取\(\max\)

$1\le k\le4 $ 表示当前需要选择丢弃\(k\)张手牌,转移为在堆顶里选一个后继续舍弃\(k-1\)个,取\(\min\)

#include<bits/stdc++.h>
#define inf 2139062143
#define ll long long
#define db double
#define ld long double
#define ull unsigned long long
#define MAXN 7001001
#define MOD 998244353
#define Fill(a,x) memset(a,x,sizeof(a))
#define rep(i,s,t) for(int i=(s),i##end=(t);i<=i##end;++i)
#define dwn(i,s,t) for(int i=(s),i##end=(t);i>=i##end;--i)
#define ren for(int i=fst[x];i;i=nxt[i])
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
using namespace std;
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
namespace CALC
{
	inline int pls(int a,int b){return a+b>=MOD?a+b-MOD:(a+b<0?a+b+MOD:a+b);}
	inline int mns(int a,int b){return a-b<0?a-b+MOD:(a-b>=MOD?a-b-MOD:a-b);}
	inline int mul(int a,int b){return (1LL*a*b)%MOD;}
	inline void inc(int &a,int b){a=pls(a,b);}
	inline void dec(int &a,int b){a=mns(a,b);}
	inline void tms(int &a,int b){a=mul(a,b);}
	inline int qp(int x,int t,int res=1)
		{for(;t;t>>=1,x=mul(x,x)) if(t&1) res=mul(res,x);return res;}
	inline int Inv(int x){return qp(x,MOD-2);}
}
using namespace CALC;
int n,len[5],f[MAXN][5],w[5],ans;
vector<int> v[5];
inline int calc(int a,int b,int c,int d)
{
	return a*w[1]+b*w[2]+c*w[3]+d;
}
int main()
{
	int st,a,b,g[5];rep(T,1,read())
	{
		n=read();rep(i,1,4) v[i].clear();
		rep(i,1,n) a=read(),b=read(),v[b].pb(a);
		rep(i,1,4) sort(v[i].begin(),v[i].end()),len[i]=v[i].size()+1;
		w[4]=1,w[3]=len[4],w[2]=len[3]*len[4],w[1]=len[2]*len[3]*len[4];
		rep(i,0,4) f[0][i]=0;
		rep(a,0,len[1]-1) rep(b,0,len[2]-1) rep(c,0,len[3]-1) rep(d,0,len[4]-1)
			if(a+b+c+d)
			{
				st=calc(a,b,c,d),g[1]=a,g[2]=b,g[3]=c,g[4]=d;
				f[st][0]=0;
				rep(i,1,4) if(g[i]) f[st][0]=max(f[st][0],f[st-w[i]][i]+v[i][g[i]-1]);
//				cout<<a<<" "<<b<<" "<<c<<" "<<d<<" : "<<st<<" "<<f[st][0]<<endl;
				rep(i,1,4) 
				{
					f[st][i]=inf;
					rep(j,1,4) if(g[j]) f[st][i]=min(f[st][i],f[st-w[j]][i-1]);
				}
			}
		printf("%d\n",f[w[1]*len[1]-1][0]);
	}
} 

F

显然可以找到一个分界点,使得该点左侧的贡献为大于\(x\)的数的个数,右侧为小于

用树状数组直接维护所有数的出现,即可\(O(log^2)\)找到分界点

统计答案可以用线段树分别维护小于/大于每个数的区间和,每次更改为区间加

#include<bits/stdc++.h>
#define inf 2139062143
#define ll long long
#define db double
#define ld long double
#define ull unsigned long long
#define MAXN 200100
#define MOD 998244353
#define Fill(a,x) memset(a,x,sizeof(a))
#define rep(i,s,t) for(int i=(s),i##end=(t);i<=i##end;++i)
#define dwn(i,s,t) for(int i=(s),i##end=(t);i>=i##end;--i)
#define ren for(int i=fst[x];i;i=nxt[i])
#define pls(a,b) (a+b)%MOD
#define mns(a,b) (a-(b))%MOD
#define mul(a,b) (1LL*(a)*(b))%MOD
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
using namespace std;
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
const int lim=2e5;
int n,q,w[MAXN];
ll pre[MAXN],suf[MAXN];
int sum[MAXN<<2];
ll sl[MAXN<<2],tl[MAXN<<2],sr[MAXN<<2],tr[MAXN<<2];
ll c[MAXN];
inline void addp(int x,int w){for(;x<=lim;x+=x&-x) c[x]+=w;}
inline ll query(int x,ll res=0){for(;x;x-=x&-x) res+=c[x];return res;}
inline ll getpre(int x){return query(x);}
inline ll getsuf(int x){return query(lim)-query(x-1);}
int find()
{
	int l=1,r=lim,mid=l+r>>1,res=-1;
	for(;l<=r;mid=l+r>>1)
		if(getpre(mid-1)<=getsuf(mid+1)) res=mid,l=mid+1;
		else r=mid-1;
	return res;
}
inline void upd(int k)
{
	sl[k]=sl[k<<1]+sl[k<<1|1],sr[k]=sr[k<<1]+sr[k<<1|1];
	sum[k]=sum[k<<1]+sum[k<<1|1];
}
inline void Mdfl(int k,int l,int r,int w)
{
	sl[k]+=1LL*sum[k]*w,tl[k]+=w;
}
inline void Mdfr(int k,int l,int r,int w)
{
	sr[k]+=1LL*sum[k]*w,tr[k]+=w;
}
inline void pshd(int k,int l,int r,int mid)
{
	if(tl[k]) Mdfl(k<<1,l,mid,tl[k]),Mdfl(k<<1|1,mid+1,r,tl[k]),tl[k]=0;
	if(tr[k]) Mdfr(k<<1,l,mid,tr[k]),Mdfr(k<<1|1,mid+1,r,tr[k]),tr[k]=0;
}
void build(int k,int l,int r)
{
	tl[k]=tr[k]=0;
	if(l==r)
	{
		sum[k]=w[l],sl[k]=pre[l-1]*w[l],sr[k]=suf[r+1]*w[l];
		return ;
	}
	int mid=l+r>>1;build(k<<1,l,mid);build(k<<1|1,mid+1,r);
	upd(k);
}
void add(int k,int l,int r,int x,int w)
{
	if(l==r)
	{
		sum[k]+=w,sl[k]+=getpre(l-1)*w,sr[k]+=getsuf(r+1)*w;
		return ;
	}
	int mid=l+r>>1;pshd(k,l,r,mid);
	if(x<=mid) add(k<<1,l,mid,x,w);
	else add(k<<1|1,mid+1,r,x,w);
	upd(k);
}
void mdfl(int k,int l,int r,int a,int b,int w)
{
	if(a<=l&&r<=b) {Mdfl(k,l,r,w);return ;}
	int mid=l+r>>1;pshd(k,l,r,mid);
	if(a<=mid) mdfl(k<<1,l,mid,a,b,w);
	if(b>mid) mdfl(k<<1|1,mid+1,r,a,b,w);
	upd(k);
}
void mdfr(int k,int l,int r,int a,int b,int w)
{
	if(a<=l&&r<=b) {Mdfr(k,l,r,w);return ;}
	int mid=l+r>>1;pshd(k,l,r,mid);
	if(a<=mid) mdfr(k<<1,l,mid,a,b,w);
	if(b>mid) mdfr(k<<1|1,mid+1,r,a,b,w);
	upd(k);
}
ll qryr(int k,int l,int r,int x)
{
	if(l==r) return sr[k];
	int mid=l+r>>1;pshd(k,l,r,mid);
	return x<=mid?qryr(k<<1,l,mid,x):sr[k<<1]+qryr(k<<1|1,mid+1,r,x);
}
ll qryl(int k,int l,int r,int x)
{
	if(l==r) return sl[k];
	int mid=l+r>>1;pshd(k,l,r,mid);
	return x<=mid?sl[k<<1|1]+qryl(k<<1,l,mid,x):qryl(k<<1|1,mid+1,r,x);
}
ll gcd(ll a,ll b){return !b?a:gcd(b,a%b);}
int main()
{
	int las,a,b,now;ll res,tot,g;
	rep(T,1,read())
	{
		n=read(),q=read();
		rep(i,1,n) w[read()]++;
		rep(i,1,lim) pre[i]=pre[i-1]+w[i];
		dwn(i,lim,1) suf[i]=suf[i+1]+w[i];
		rep(i,1,lim) if(w[i]) addp(i,w[i]);
		build(1,1,lim);
		while(q--)
		{
			a=read();
			if(a==2)
			{
				now=find(),res=qryr(1,1,lim,now);
				if(now<lim) res+=qryl(1,1,lim,now+1);
				tot=1LL*sum[1]*(sum[1]-1);
				g=gcd(res,tot);
				printf("%lld/%lld\n",res/g,tot/g);
			}
			else
			{
				a=read(),b=read();addp(b,a);
				add(1,1,lim,b,a);
                if(b-1>=1) mdfr(1,1,lim,1,b-1,a);
                if(b+1<=lim) mdfl(1,1,lim,b+1,lim,a);
			}
		}
		rep(i,1,lim) w[i]=pre[i]=suf[i]=c[i]=0;
	}
}

G

直接维护这个链表,记录一下中点以及中点右侧点的集合。

删除与添加操作分别根据奇偶性讨论即可

#include<bits/stdc++.h>
#define inf 2139062143
#define ll long long
#define db double
#define ld long double
#define ull unsigned long long
#define MAXN 10010010
#define MOD 998244353
#define Fill(a,x) memset(a,x,sizeof(a))
#define rep(i,s,t) for(int i=(s),i##end=(t);i<=i##end;++i)
#define dwn(i,s,t) for(int i=(s),i##end=(t);i>=i##end;--i)
#define ren for(int i=fst[x];i;i=nxt[i])
#define pls(a,b) (a+b)%MOD
#define mns(a,b) (a-(b))%MOD
#define mul(a,b) (1LL*(a)*(b))%MOD
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
using namespace std;
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
int q,pre[MAXN],suf[MAXN],tot,n,ans,now,in[MAXN];
char s[5];
int main()
{
	int x,l,r;while(scanf("%d",&q)!=EOF)
	{
		rep(i,1,q)
		{
			scanf("%s",s+1);
			if(s[1]=='L')
			{
				tot++,now++;
				if(tot==1) pre[now]=suf[now]=0,suf[0]=pre[0]=now,ans=now,in[ans]=1;
				else
				{
					suf[now]=suf[0],pre[suf[0]]=now,pre[now]=0,suf[0]=now;
					if(tot&1) ans=pre[ans],in[ans]++;
				}
			}
			else if(s[1]=='R')
			{
				tot++,now++,in[now]++;
				if(tot==1) pre[now]=suf[now]=0,suf[0]=pre[0]=now,ans=now;
				else
				{
					pre[now]=pre[0],suf[pre[0]]=now,suf[now]=0,pre[0]=now;
					if(tot%2==0) in[ans]--,ans=suf[ans];
				}
			}
			else if(s[1]=='Q') printf("%d\n",ans);
			else 
			{
				x=read();l=pre[x],r=suf[x];
				suf[l]=r,pre[r]=l;
				tot--;
				if(x==ans) {if(tot&1) ans=l,in[l]++;else ans=r;}
				else if(in[x]) {if(tot&1) ans=pre[ans],in[ans]++;}
				else {if(tot%2==0) in[ans]--,ans=suf[ans];}
				in[x]=0;
			}
		}
		while(ans) in[ans]=0,ans=suf[ans];tot=now=0;
	}
}

H

考虑取\(m=2\),则显然有最终答案\(\ge \frac{n}{2}\),考虑随机化令一个数在答案集合内

对于已知一个数的情况,朴素的想法是将其他数与这个数作差,想要找到一个质数\(m\)使得尽可能多的差是\(m\)的倍数

因为集合内的数较多,可以考虑再进行一次随机化,假定这个差也在集合中

则只需要先预处理出\(\sqrt{w}\)内的所有素数,对这个差进行质因数分解,然后\(check\)所有质因数的贡献

每次错误的概率为\((1-\frac{1}{4})\),随机化\(30\)次错误的概率很低

#include<bits/stdc++.h>
#define inf 2139062143
#define ll long long
#define db double
#define ld long double
#define ull unsigned long long
#define MAXN 200100
#define MOD 998244353
#define Fill(a,x) memset(a,x,sizeof(a))
#define rep(i,s,t) for(int i=(s),i##end=(t);i<=i##end;++i)
#define dwn(i,s,t) for(int i=(s),i##end=(t);i>=i##end;--i)
#define ren for(int i=fst[x];i;i=nxt[i])
#define pls(a,b) (a+b)%MOD
#define mns(a,b) (a-(b))%MOD
#define mul(a,b) (1LL*(a)*(b))%MOD
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
using namespace std;
inline ll read()
{
    ll x=0,f=1;char ch=getchar();
    while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
int n,ntp[MAXN*10],p[MAXN*10],tot,ans,m;
ll g[MAXN],h[MAXN],f[MAXN];
void mem(int n=2e6)
{
	rep(i,2,n)
	{
		if(!ntp[i]) p[++tot]=i;
		rep(j,1,tot) if(i*p[j]>n) break;
			else {ntp[i*p[j]]=1;if(i%p[j]==0) break;}
	}
}
int solve(int pos,ll diff,int res=0)
{
	m=0;rep(i,1,tot)
		if(1LL*p[i]*p[i]>diff) break;
		else if(diff%p[i]==0)
			{h[++m]=p[i];while(diff%p[i]==0) diff/=p[i];}
	if(diff>1) h[++m]=diff;int tmp;
	rep(i,1,n) f[i]=abs(g[i]-g[pos]);
	rep(i,1,m)
	{
		tmp=0;
		rep(j,1,n) tmp+=(f[j]%h[i]==0);
		res=max(res,tmp);
	}
	return res;
}
int main()
{
	mem();int x,y;srand(19260817);
	rep(T,1,read())
	{
		n=read(),ans=1;rep(i,1,n) g[i]=read();
		rep(t,1,30) 
		{
			x=rand()%n+1,y=rand()%n+1;
			while(x==y) y=rand()%n+1;
			ans=max(solve(x,abs(g[x]-g[y])),ans);
		}
		printf("%d\n",ans);
	}
}

I

奇怪的题 弃了

J

首先可以对\(a,b\)分别得到一个有效分数的区间,在区间外的贡献为最小值或最大值

有两种显然的情况,即完全不可能或一定可以达到目的

否则显然可以在有效区间内进行合法的选数使得\(a\)的分数恰好大于\(b\),此时的贡献为已有的二者分数之差

考虑能使答案更优的特殊情况,一定是在分数不变的情况下\(a_n\)更小或\(b_n\)更大

这两种情况分别发生在区间的左侧与右侧,判断一下二者的左侧区间与右侧区间本身是否合法

#include<bits/stdc++.h>
#define inf 2139062143
#define ll long long
#define db double
#define ld long double
#define ull unsigned long long
#define MAXN 100100
#define MOD 998244353
#define Fill(a,x) memset(a,x,sizeof(a))
#define rep(i,s,t) for(int i=(s),i##end=(t);i<=i##end;++i)
#define dwn(i,s,t) for(int i=(s),i##end=(t);i>=i##end;--i)
#define ren for(int i=fst[x];i;i=nxt[i])
#define pls(a,b) (a+b)%MOD
#define mns(a,b) (a-(b))%MOD
#define mul(a,b) (1LL*(a)*(b))%MOD
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
using namespace std;
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
ll n,a[MAXN],b[MAXN],s,t,h,ans,la,ra,lb,rb,res;
ll sa,sb;
int main()
{
	rep(T,1,read()) 
	{
		n=read(),s=read(),t=read(),h=read();
		rep(i,1,n-1) a[i]=read();rep(i,1,n-1) b[i]=read();
		sort(a+1,a+n);sort(b+1,b+n);
		ans=inf,sa=sb=0;ll tmp;
		rep(i,t+1,n-1-s) sa+=a[i],sb+=b[i];
		if(t) la=a[t],lb=b[t];else la=lb=1;
		if(s) ra=a[n-s],rb=b[n-s];else ra=rb=h;
		if(sa+ra<=sb+lb) {puts("IMPOSSIBLE");continue;}
		if(sa+la>sb+rb) {printf("%lld\n",1-h);continue;}
		res=ans=sb-sa+1;
		if(sa+la>sb+lb) ans=min(ans,res-la+1);
		if(sa+ra>sb+rb) ans=min(ans,res-h+rb);
		printf("%lld\n",ans);
	}
}

K

看上去可做的虚树+树剖题 咕

posted @ 2021-08-17 23:50  jack_yyc  阅读(44)  评论(0编辑  收藏  举报