省选模拟3

A. 人脑图灵机

先一直用 \(b\) 然后再看是否大于目标,小于直接 \(No\)

最后看看 \(m \% b\) 的余数,还有剩下的炮弹数

如果剩下的炮弹数大于等于 \(2\) 可以直接 \(Yes\) ,因为两个 \(0.5b\) 可以凑出所有的余数

如果余数小于等于 \(0.5\) 也可以直接 \(Yes\)

那么剩下的情况就是发射一发 \(a\) 了,可以考虑推掉一些 \(b\) 换成 \(a\)

\(c=b-a\)

那么这个余数合法当且仅当 \(res+x*c=a\) 同时 \(x\) 小于等于发射的炮弹数

注意一开始的判断会爆,需要用 \(\_\_int128\)

感觉很像 \(CF\)

Code
#include<bits/stdc++.h>
#define int __int128
#define rint signed
#define inf 0x3f3f3f3f3f3f3f3f
using namespace std;
inline int read(){
	int x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
	return x*f;
}
int T,n,m,a,b,c,mx,res,w;
inline void solve(){
	n=read(),m=read(),a=read(),b=read();c=b-a;
	if(b*n<m) return puts("No"),void();
	res=m-b*(m/b),w=n-m/b;
	if(w>=2) return puts("Yes"),void();
	if(!res) return puts("Yes"),void();
	if(res<=(b/2)&&w>=1) return puts("Yes"),void();
	if(res==a) return puts("Yes"),void();
	if((a-res)%c==0&&(a-res)/c<=(m/b)) return puts("Yes"),void();
	return puts("No"),void();
}
signed main(){
#ifdef LOCAL
	freopen("in","r",stdin);
	freopen("out","w",stdout);
#endif
	freopen("turing.in","r",stdin);
	freopen("turing.out","w",stdout);
	T=read();while(T--) solve();
	return 0;
}

B. 超脑星球

把每一对 \(a\) 抽象成线段,把 \(b\) 抽象成点,再把他们放到数轴上

再依次考虑增加选择的点数,贪心的考虑一定是从左右两边来进行选择的

所以可以用一个双指针,分别为 \(l,r\)

设线段的左右端点分别为 \(mn,mx\)

对于左边的,然后选择一条线段去匹配,发现贡献分为了两部分,一部分是二倍的到左端点的距离,一部分是线段的长度

那么贡献就是 \(mn-b_l\) ,右边的为 \(b_r-mx\) 都要乘 \(2\)

还有一种情况就是原先跟右边匹配的线段现在去跟左边匹配了

然后我们需要再给原来匹配的点再找一条新的线段

画一下图发现贡献为 \(mn+mx-b_l-mx'\)\(mx'\) 为新找的线段

右边也有这样的情况,贡献为 \(b_r-mx-mn-mn'\)\(mn'\) 为新找的线段

分别维护一下最值就行,主要到贡献不能为负,因为最次在两个数中间,这个要特判一下

下面两种用了反悔贪心的思路

好像是种套路?叫模拟费用流 UOJ455和这个题感觉很像

Code
#include<bits/stdc++.h>
#define int long long
#define rint signed
#define inf 0x3f3f3f3f3f3f3f3f
using namespace std;
inline int read(){
	int x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
	return x*f;
}
int n,m,l,r;
int a[100010],b[100010];
int ans[100010],c;
struct Seg{int mn,mx;}seg[100010];
set<pair<int,int>>S[5];
bool vis[100010];
signed main(){
#ifdef LOCAL
	freopen("in","r",stdin);
	freopen("out","w",stdout);
#endif
	freopen("brain.in","r",stdin);
	freopen("brain.out","w",stdout);
	n=read(),m=read();l=1,r=m;
	for(int i=1;i<=n;i++) a[i]=read();
	for(int i=1;i<=m;i++) b[i]=read();sort(b+1,b+1+m);
	for(int i=1;i<n;i++) ans[0]+=abs(a[i]-a[i+1]);
	for(int i=1;i<n;i++){
		seg[i].mn=min(a[i],a[i+1]),seg[i].mx=max(a[i],a[i+1]);
		S[1].insert(make_pair(seg[i].mn,i));
		S[2].insert(make_pair(seg[i].mx,i));
	}
	while(l<=r){
		int res1=-1,res2=-1,res3=-1,res4=-1,id1=-1,id2=-1,id3=-1,id4=-1;c++;
		id1=(*S[1].rbegin()).second;
		id2=(*S[2].begin()).second;
		if(!S[3].empty()) id3=(*S[3].rbegin()).second;
		if(!S[4].empty()) id4=(*S[4].begin()).second;
		res1=seg[id1].mn-b[l];
		res2=b[r]-seg[id2].mx;
		if(id3!=-1) res3=seg[id3].mn+seg[id3].mx-b[l]-seg[id2].mx;
		if(id4!=-1) res4=b[r]-seg[id4].mx-seg[id4].mn+seg[id1].mn;
		res1*=2;res2*=2;res3*=2;res4*=2;
		if(res1>=res2&&res1>=res3&&res1>=res4){
			ans[c]=ans[c-1]+res1;l++;
			S[1].erase(S[1].find(make_pair(seg[id1].mn,id1)));
			S[2].erase(S[2].find(make_pair(seg[id1].mx,id1)));
			S[4].insert(make_pair(seg[id1].mn+seg[id1].mx,id1));
		}else if(res2>=res1&&res2>=res3&&res2>=res4){
			ans[c]=ans[c-1]+res2;r--;
			S[1].erase(S[1].find(make_pair(seg[id2].mn,id2)));
			S[2].erase(S[2].find(make_pair(seg[id2].mx,id2)));
			S[3].insert(make_pair(seg[id2].mn+seg[id2].mx,id2));
		}else if(res3>=res1&&res3>=res2&&res3>=res4){
			ans[c]=ans[c-1]+res3;l++;
			S[1].erase(S[1].find(make_pair(seg[id2].mn,id2)));
			S[2].erase(S[2].find(make_pair(seg[id2].mx,id2)));
			S[3].insert(make_pair(seg[id2].mn+seg[id2].mx,id2));
			S[3].erase(S[3].find(make_pair(seg[id3].mn+seg[id3].mx,id3)));
			S[4].insert(make_pair(seg[id3].mn+seg[id3].mx,id3));
		}else{
			ans[c]=ans[c-1]+res4;r--;
			S[1].erase(S[1].find(make_pair(seg[id1].mn,id1)));
			S[2].erase(S[2].find(make_pair(seg[id1].mx,id1)));
			S[4].insert(make_pair(seg[id1].mn+seg[id1].mx,id1));
			S[4].erase(S[4].find(make_pair(seg[id4].mn+seg[id4].mx,id4)));
			S[3].insert(make_pair(seg[id4].mn+seg[id4].mx,id4));
		}
		if(ans[c]<ans[c-1]) ans[c]=ans[c-1];
	}
	for(int i=1;i<=m;i++) printf("%lld ",ans[i]);
	return 0;
}

C. 暗星人

给出的 \(F\) 可以变成前边的维护一个乘法和加法的标记,后边的为取 \(\max\)

发现限制一共两维,于是用数据结构套一下就行,外层维护时间,内层维护 \(L,R\)

这里我用的是分块套线段树

里面查询有个优化就是查询时没有左右儿子就不 \(pushdown\) (虽然因为写假了,并没有起到作用,但还是过了,就不管了

Code
#include<bits/stdc++.h>
#define int long long
#define rint signed
#define lson t[x].ls
#define rson t[x].rs
#define inf 0x3f3f3f3f3f3f3f3f
#define mod 2677114440
using namespace std;
inline int read(){
	int x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
	return x*f;
}
const int blo=2500;
int n,m,typ,lst,tot;
int bl[300010],L[125],R[125];
struct node{int l,r,a,b;}T[300010];
struct Seg{
	rint ls,rs;
	int addtag,multag,mxtag;
}t[65000010];
inline rint newSeg(){tot++;t[tot].addtag=0,t[tot].multag=1,t[tot].mxtag=0;return tot;}
struct BLOCK{
	rint rt;
	inline void pushdown(rint x){
		if(!lson) lson=newSeg();
		if(!rson) rson=newSeg();
		t[lson].mxtag=max(t[lson].mxtag,t[x].mxtag);
		t[rson].mxtag=max(t[rson].mxtag,t[x].mxtag);
		t[lson].addtag=(t[lson].addtag*t[x].multag+t[x].addtag)%mod;
		t[rson].addtag=(t[rson].addtag*t[x].multag+t[x].addtag)%mod;
		t[lson].multag=t[lson].multag*t[x].multag%mod;
		t[rson].multag=t[rson].multag*t[x].multag%mod;
		t[x].addtag=0,t[x].mxtag=0,t[x].multag=1;
	}
	void upd(rint &x,int l,int r,int L,int R,int a,int b){
		if(!x) x=newSeg();
		if(L<=l&&r<=R) return t[x].addtag=(t[x].addtag*a+b)%mod,t[x].multag=t[x].multag*a%mod,t[x].mxtag=max(t[x].mxtag,b),void();
		pushdown(x);
		int mid=(l+r)>>1;
		if(L<=mid) upd(lson,l,mid,L,R,a,b);
		if(R>mid) upd(rson,mid+1,r,L,R,a,b);
	}
	void query(rint x,int l,int r,int pos,int &X,int &Y){
		if(!x||l==r) return X=(X*t[x].multag+t[x].addtag)%mod,Y=max(Y,t[x].mxtag),void();
		pushdown(x);
		int mid=(l+r)>>1;
		if(pos<=mid) query(lson,l,mid,pos,X,Y);
		else query(rson,mid+1,r,pos,X,Y);
	}
	#undef lson
	#undef rson
}B[125];
inline void ins(int pos){if(R[bl[pos]]==pos) for(int i=L[bl[pos]];i<=R[bl[pos]];i++) B[bl[pos]].upd(B[bl[pos]].rt,1,1000000,T[i].l,T[i].r,T[i].a,T[i].b);}
inline void query(int l,int r,int &x,int &y,int pos){
	if(bl[l]==bl[r]){
		for(int i=l;i<=r;i++) if(T[i].l<=pos&&pos<=T[i].r){
			x=(x*T[i].a+T[i].b)%mod;
			y=max(y,T[i].b);
		}
		return ;
	}
	for(int i=l;i<=R[bl[l]];i++) if(T[i].l<=pos&&pos<=T[i].r){
		x=(x*T[i].a+T[i].b)%mod;
		y=max(y,T[i].b);
	}
	for(int i=bl[l]+1;i<=bl[r]-1;i++) B[i].query(B[i].rt,1,1000000,pos,x,y);
	for(int i=L[bl[r]];i<=r;i++) if(T[i].l<=pos&&pos<=T[i].r){
		x=(x*T[i].a+T[i].b)%mod;
		y=max(y,T[i].b);
	}
}
signed main(){
#ifdef LOCAL
	freopen("in","r",stdin);
	freopen("out","w",stdout);
#endif
	freopen("dark.in","r",stdin);
	freopen("dark.out","w",stdout);
	n=read(),m=read(),typ=read();
	for(int i=1;i<=m;i++) bl[i]=(i-1)/blo+1;
	for(int i=1;i<=120;i++) L[i]=(i-1)*blo+1,R[i]=min(i*blo,m);
	for(int i=1,l,r,pos,x,y;i<=m;i++){
		T[i].l=read(),T[i].r=read(),T[i].a=read(),T[i].b=read();
		l=read(),r=read(),pos=read(),x=read(),y=0;
		if(typ) T[i].l^=lst,T[i].r^=lst,T[i].a^=lst,T[i].b^=lst,l^=lst,r^=lst,pos^=lst,x^=lst;
		ins(i);query(l,r,x,y,pos);
		printf("%lld\n",lst=(x^y));
	}
	return 0;
}
posted @ 2022-01-15 18:00  Max_QAQ  阅读(58)  评论(0编辑  收藏  举报