省选模拟3.13

A. 跑步

只想到了每次修改的小方格内的左端点是单调的

一开始以为右端点和左端点一样是不断向里走的,然后发现错了

就没想到,右端点也是单调向右走的

然后用树状数组维护每个位置的 \(f\) 值就行了

然后再判断每次修改的左右端点是否移动就好了

Code
#include<bits/stdc++.h>
#define int long long//OVERFLOW !!! MEMORY LIMIT !!!
#define lowbit(x) x&-x
#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,ans;
int a[2010][2010],f[2010][2010];
char str[10];
struct bit{
	int a[2010];
	inline void upd(int x,int k){
		for(;x<=n;x+=lowbit(x)) a[x]+=k;
	}
	inline int query(int x){
		if(!x) return 0;int res=0;
		for(;x;x-=lowbit(x)) res+=a[x];
		return res;
	}
}BIT[2010];
inline void upd(int x,int y,int k){
	int l=y,r=y+1;a[x][y]+=k;r=min(r,n);
	for(int i=x;i<=n;i++){
		while(l<=n&&((max(BIT[i].query(l-1)  ,BIT[i-1].query(l))+a[i][l])==BIT[i].query(l))) l++;
		while(r<=n&&((max(BIT[i].query(r-1)+k,BIT[i-1].query(r))+a[i][r])!=BIT[i].query(r))) r++;
		if(l>n) break;BIT[i].upd(l,k);BIT[i].upd(r,-k);ans+=(r-l)*k;
	}
}
signed main(){
#ifdef LOCAL
	freopen("in","r",stdin);
	freopen("out","w",stdout);
#endif
	freopen("run.in","r",stdin);
	freopen("run.out","w",stdout);
	n=read();
	for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) a[i][j]=read();
	for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) f[i][j]=max(f[i-1][j],f[i][j-1])+a[i][j];
	for(int i=1;i<=n;i++) for(int j=1;j<=n;j++){
		BIT[i].upd(j  , f[i][j]);
		BIT[i].upd(j+1,-f[i][j]);
	}
	for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) ans+=f[i][j];printf("%lld\n",ans);
	for(int i=1,x,y;i<=n;i++){
		scanf("%s",str+1);x=read(),y=read();
		upd(x,y,((str[1]=='U')?(1):(-1)));
		printf("%lld\n",ans);
	}
	return 0;
}

B. 算术

考虑整个 \(k\) 次剩余

只要检验 \(n\) 是否存在 \(k\) 次剩余即可

可以选择若干个模数 \(P\) ,若都存在 \(k\) 次剩余

\(n\) 可能存在,若有一个不存在那 \(n\) 一定不存在 \(k\) 次剩余

那么考虑如何检验

如果模数形如 \(ak+1\)

那么 \(x^{ak}\equiv 1(\text{mod }P)\)

又因为 \(x^k=n\) 所以 \(n^a\equiv 1(\text{mod }P)\)

这样就方便检验了

Code
#include<bits/stdc++.h>
#define int long long//OVERFLOW !!! MEMORY LIMIT !!!
#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,k,c,n,len,mod;
char st[1000010];
bool jud;
inline int check(int x){for(int i=2;i*i<=x;i++) if(x%i==0) return false;return true;}
inline void getn(){n=0;for(int i=1;i<=len;i++) n=(n*10+st[i]-'0')%mod;}
inline int qpow(int x,int k){
	int res=1,base=x;
	while(k){if(k&1) res=res*base%mod;base=base*base%mod;k>>=1;}
	return res;
}
inline void solve(){
	scanf("%s",st+1);len=strlen(st+1);k=read();c=0;jud=1;
	for(int i=800;;i++) if(check(i*k+1)){
		mod=i*k+1;getn();
		if(qpow(n,i)!=1) jud=0;if(!jud) break;
		c++;if(c==10) break;
	}
	puts(jud?"Y":"N");
}
signed main(){
#ifdef LOCAL
	freopen("in","r",stdin);
	freopen("out","w",stdout);
#endif
	freopen("math.in","r",stdin);
	freopen("math.out","w",stdout);
	T=read();while(T--) solve();
	return 0;
}

C. 求和

暴力乱搞

考虑答案出现的位置 \(x,y\)

如果修改的位置为其中一个,分类讨论修改后的值是变大还是变小

变大的话直接给答案加,变小的话全局暴力查

如果修改的是其他位置,还是这么分类讨论

变大的话就查询一下周围的 \(k\) 个值,再和答案比较

变小的话就只修改值

正解的话就是维护以 \(a_i\) 为区间最大值的所有对数

修改时只考虑可能对答案有影响的位置

先查询 \(a_i\) 左右两边的 \(K\) 个区间的最大值,和 \(a_i\) 进行比较,如果比 \(a_i\) 要小,就更新 \(i\) 这个位置

否则就更新最大值的位置,然后再查询左右 \(K\) 个的值

如果他是最大值那就更新这个位置,否则不更新这个位置

Code
#include<bits/stdc++.h>
#define int long long//OVERFLOW !!! MEMORY LIMIT !!!
#define rint signed
#define lson rt<<1
#define rson rt<<1|1
#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,K,q,op,p;
int ans,x,y;
int a[1000010];
pair<int,int> t[1000010];
struct seg{int mx,pos;}st[1000010*4],t1,t2;
inline void pushup(int rt){
	st[rt].mx=max(st[lson].mx,st[rson].mx);
	if(st[rt].mx==st[lson].mx) st[rt].pos=st[lson].pos;
	if(st[rt].mx==st[rson].mx) st[rt].pos=st[rson].pos;
}
void build(int rt,int l,int r){
	if(l==r) return st[rt].mx=a[l],st[rt].pos=l,void();
	int mid=(l+r)>>1;
	build(lson,l,mid);
	build(rson,mid+1,r);
	pushup(rt);
}
void upd(int rt,int l,int r,int pos,int k){
	if(l==r) return st[rt].mx=k,void();
	int mid=(l+r)>>1;
	if(pos<=mid) upd(lson,l,mid,pos,k);
	else upd(rson,mid+1,r,pos,k);
	pushup(rt);
}
seg query(int rt,int l,int r,int L,int R){
	if(L<=l&&r<=R) return st[rt];
	int mid=(l+r)>>1;seg res,t;res.mx=-inf,res.pos=0;
	if(L<=mid){
		t=query(lson,l,mid,L,R);
		res.mx=max(res.mx,t.mx);if(res.mx==t.mx) res.pos=t.pos;
	}
	if(R>mid){
		t=query(rson,mid+1,r,L,R);
		res.mx=max(res.mx,t.mx);if(res.mx==t.mx) res.pos=t.pos;
	}
	return res;
}
inline void solve(){
	ans=-inf;
	for(int i=1,l,r;i<=n;i++){
		t1=query(1,1,n,1,n);if(t1.mx*2<=ans) break;
		t[++p]=make_pair(t1.pos,t1.mx);upd(1,1,n,t1.pos,-inf);
		l=max(t1.pos-K,1ll);r=min(t1.pos+K,n);
		t2=query(1,1,n,l,r);
		ans=max(ans,t1.mx+t2.mx);if(ans==t1.mx+t2.mx) x=t1.pos,y=t2.pos;
	}
	while(p){upd(1,1,n,t[p].first,t[p].second);p--;}
}
signed main(){
#ifdef LOCAL
	freopen("in","r",stdin);
	freopen("out","w",stdout);
#endif
	freopen("sum.in","r",stdin);
	freopen("sum.out","w",stdout);
	n=read(),K=read(),q=read(),op=read();
	for(int i=1;i<=n;i++) a[i]=read();
	build(1,1,n);solve();printf("%lld\n",ans);
	for(int i=1,pos,k,l,r;i<=q;i++){
		pos=read()^(op*ans),k=read()^(op*ans);
		if(pos==x||pos==y){
			if(a[pos]>k){upd(1,1,n,pos,k);solve();}
			else{ans+=k-a[pos];upd(1,1,n,pos,k);}
		}else{
			if(a[pos]>k){
				upd(1,1,n,pos,k);
			}else{
				upd(1,1,n,pos,-inf);
				l=max(pos-K,1ll);r=min(pos+K,n);
				t1=query(1,1,n,l,r);
				ans=max(ans,t1.mx+k);
				if(ans==t1.mx+k) x=t1.pos,y=pos;
				upd(1,1,n,pos,k);
			}
		}
		a[pos]=k;
		printf("%lld\n",ans);
	}
	return 0;
}
posted @ 2022-03-13 19:50  Max_QAQ  阅读(46)  评论(0编辑  收藏  举报