省選模擬3.13
阿新 • • 發佈:2022-03-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\) 個值,再和答案比較
變小的話就只修改值
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; }