1. 程式人生 > 其它 >noip模擬65(待補)

noip模擬65(待補)

「網格圖·序列問題· 置換· 同桌的你」

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);
}

C. 置換

D. 同桌的你