noip模擬65(待補)
阿新 • • 發佈:2021-09-29
「網格圖·序列問題· 置換· 同桌的你」
A. 網格圖
簽到題,大模擬.
A_code
#include<bits/stdc++.h> using namespace std; namespace BSS { #define ll long long int #define ull unsigned ll #define lf double #define lbt(x) (x&(-x)) #define mp(x,y) make_pair(x,y) #define lb lower_bound #define ub upper_bound #define Fill(x,y) memset(x,y,sizeof x) #define Copy(x,y) memcpy(x,y,sizeof x) #define File(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout) inline ll read() { ll res=0; bool cit=1; char ch; while(!isdigit(ch=getchar())) if(ch=='-') cit=0; while(isdigit(ch)) res=(res<<3)+(res<<1)+(ch^48),ch=getchar(); return cit?res:-res; } } using namespace BSS; const ll N=507; ll m,n,cnt,ans,fans; ll fa[N*N],son[N*N]; ll id[N][N],val[N][N]; vector<ll> vec[N*N]; unordered_map<ll,ll> mp1; struct I { ll x,y; } p[N*N]; ll getfa(ll x){ return x==fa[x] ? x : fa[x]=getfa(fa[x]) ; } inline void change(ll x,ll opt){ if(opt){ if(!mp1[x]) ans+=son[x]; mp1[x]++; } else if(!(--mp1[x])) ans-=son[x],mp1.erase(x); } inline void solve(ll i,ll j,ll opt){ // opt==1 為增添 if(i>n or j>n) return; if(val[i][j]) change(getfa(id[i][j]),opt); else{ opt ? ans++ : ans--; for(auto w : vec[id[i][j]]){ change(w,opt); } } } inline void Work_Odd(ll x){ for(int i=1;i<=n-m;i++){ for(int j=x;j<=x+m-1;j++){ solve(j,i,0),solve(j,i+m,1); } fans=max(ans,fans); } } inline void Work_Even(ll x){ for(int i=n;i>=m+1;i--){ for(int j=x;j<=x+m-1;j++){ solve(j,i,0),solve(j,i-m,1); } fans=max(ans,fans); } } signed main(){ File(grid); n=read(),m=read(); char s[N]; ll x,y,res; for(int i=1;i<=n;i++){ scanf("%s",s+1); for(int j=1;j<=n;j++){ id[i][j]=++cnt,p[cnt].x=i,p[cnt].y=j; val[i][j]=(s[j]=='.'); } } for(int i=1;i<=cnt;i++) fa[i]=i,son[i]=0; for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ if(val[i][j] and val[i][j+1]) fa[getfa(id[i][j+1])]=getfa(id[i][j]); if(val[i][j] and val[i+1][j]) fa[getfa(id[i+1][j])]=getfa(id[i][j]); } } for(int i=1;i<=cnt;i++){ if(!val[i]) continue; son[getfa(i)]++,fans=max(fans,son[getfa(i)]); } for(int i=1;i<=cnt;i++){ x=p[i].x,y=p[i].y; if(val[x][y]) continue; if(val[x-1][y]) vec[i].push_back(getfa(id[x-1][y])); if(val[x][y-1]) vec[i].push_back(getfa(id[x][y-1])); if(val[x+1][y]) vec[i].push_back(getfa(id[x+1][y])); if(val[x][y+1]) vec[i].push_back(getfa(id[x][y+1])); } for(int i=1;i<=m;i++){ for(int j=1;j<=m;j++) solve(i,j,1); } fans=max(fans,ans); for(int i=1;i<=n-m+1;i++){ if(i&1){ Work_Odd(i); for(int j=n;j>=n-m+1;j--){ solve(i,j,0),solve(i+m,j,1); } fans=max(fans,ans); } else{ Work_Even(i); for(int j=1;j<=m;j++){ solve(i,j,0),solve(i+m,j,1); } fans=max(fans,ans); } } printf("%lld\n",fans),exit(0); }
B. 序列問題
簽到題.
發現轉移的話需要滿足三個條件:\(i<j,a_i<a_j,i-a_i\le j-a_j\).
可以用 \(CDQ\) 分治 \(O(nlog^2n)\)卡常過去.
另外發現如果滿足後兩個條件,那麼第一個條件一定滿足.
於是複雜度可以直接降到 \(O(nlogn)\).
另外不用 \(BIT\),直接二分也可以做.
B_code
#include<bits/stdc++.h> using namespace std; namespace BSS { #define ll long long int #define ull unsigned ll #define lf double #define lbt(x) (x&(-x)) #define mp(x,y) make_pair(x,y) #define lb lower_bound #define ub upper_bound #define Fill(x,y) memset(x,y,sizeof x) #define Copy(x,y) memcpy(x,y,sizeof x) #define File(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout) inline ll read() { ll res=0; bool cit=1; char ch; while(!isdigit(ch=getchar())) if(ch=='-') cit=0; while(isdigit(ch)) res=(res<<3)+(res<<1)+(ch^48),ch=getchar(); return cit?res:-res; } } using namespace BSS; const ll N=5e5+21; ll m,n,cnt,ans,alls; struct I { ll w,id,pos,res; } p[N]; struct Bit_Array{ ll res; ll c[N<<2]; inline void update(ll x,ll w){ for(;x<=alls;x+=lbt(x)) c[x]=max(c[x],w); } inline void del(ll x){ assert(x); for(;x<=alls;x+=lbt(x)) c[x]=0; } inline ll query(ll x){ res=0; for(;x>0;x&=(x-1)) res=max(res,c[x]); return res; } } bit; inline bool cmp1(I i,I j){ if(i.w!=j.w) return i.w<j.w; if(i.pos!=j.pos) return i.pos<j.pos; return i.id<j.id; } inline bool cmp2(I i,I j){ return i.id<j.id; } void cdq(ll l,ll r){ if(l>r) return ; if(l==r) return p[l].res=max(p[l].res,1ll),void(); ll mid=(l+r)>>1; cdq(l,mid); sort(p+l,p+mid+1,cmp1),sort(p+mid+1,p+r+1,cmp1); ll p1=l,p2=mid+1,res; while(p1<=mid and p2<=r){ if(p[p1].w>=p[p2].w){ res=bit.query(p[p2].pos),p[p2].res=max(p[p2].res,res+1),p2++; } else{ bit.update(p[p1].pos,p[p1].res),p1++; } } while(p2<=r){ res=bit.query(p[p2].pos),p[p2].res=max(p[p2].res,res+1),p2++; } for(int i=l;i<p1;i++) bit.del(p[i].pos); sort(p+mid+1,p+r+1,cmp2); cdq(mid+1,r); } signed main(){ File(sequence); n=read(); ll w; for(ll i=1;i<=n;i++){ if((w=read())>i) continue; p[++cnt].w=w,p[cnt].id=i,p[cnt].pos=i-w+1; } alls=n,n=cnt,cdq(1,n); for(int i=1;i<=n;i++) ans=max(ans,p[i].res); printf("%lld\n",ans),exit(0); }