充实的感情产生出了希冀 机械的手心不自主向人类学习 你想得到什么东西

test18

签到题sign

好像做过,设 \(f(i)\) 表示选定 \(k=i\) 时的答案,这个显然可以 \(O(n)\) 求出来,写一个 nth_element 即可。

首先 \(f(n-k+1)\) 最大,具体的可以假设最后一个区间被选取,因为区间包含,贡献可以一直替换到一个不选的位置,最小长度二分就好了。yy 一下好像也可以查找每一个位置的最小贡献长度然后直接算出来。

#define _CRT_SECURE_NO_WARNINGS
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
#pragma GCC optimize("-fgcse")
#pragma GCC optimize("-fgcse-lm")
#pragma GCC optimize("-fipa-sra")
#pragma GCC optimize("-ftree-pre")
#pragma GCC optimize("-ftree-vrp")
#pragma GCC optimize("-fpeephole2")
#pragma GCC optimize("-ffast-math")
#pragma GCC optimize("-fsched-spec")
#pragma GCC optimize("unroll-loops")
#pragma GCC optimize("-falign-jumps")
#pragma GCC optimize("-falign-loops")
#pragma GCC optimize("-falign-labels")
#pragma GCC optimize("-fdevirtualize")
#pragma GCC optimize("-fcaller-saves")
#pragma GCC optimize("-fcrossjumping")
#pragma GCC optimize("-fthread-jumps")
#pragma GCC optimize("-funroll-loops")
#pragma GCC optimize("-fwhole-program")
#pragma GCC optimize("-freorder-blocks")
#pragma GCC optimize("-fschedule-insns")
#pragma GCC optimize("inline-functions")
#pragma GCC optimize("-ftree-tail-merge")
#pragma GCC optimize("-fschedule-insns2")
#pragma GCC optimize("-fstrict-aliasing")
#pragma GCC optimize("-fstrict-overflow")
#pragma GCC optimize("-falign-functions")
#pragma GCC optimize("-fcse-skip-blocks")
#pragma GCC optimize("-fcse-follow-jumps")
#pragma GCC optimize("-fsched-interblock")
#pragma GCC optimize("-fpartial-inlining")
#pragma GCC optimize("no-stack-protector")
#pragma GCC optimize("-freorder-functions")
#pragma GCC optimize("-findirect-inlining")
#pragma GCC optimize("-fhoist-adjacent-loads")
#pragma GCC optimize("-frerun-cse-after-loop")
#pragma GCC optimize("inline-small-functions")
#pragma GCC optimize("-finline-small-functions")
#pragma GCC optimize("-ftree-switch-conversion")
#pragma GCC optimize("-foptimize-sibling-calls")
#pragma GCC optimize("-fexpensive-optimizations")
#pragma GCC optimize("-funsafe-loop-optimizations")
#pragma GCC optimize("inline-functions-called-once")
#pragma GCC optimize("-fdelete-null-pointer-checks")


#include<bits/stdc++.h>
#define int long long
#define up(i,l,r) for(int i=l; i<=r; ++i)
#define dn(i,r,l) for(int i=r; i>=l; --i)

using namespace std;

const int N=100005, M=21;

int T, n, k, t, len, m, a[N], mx[N][M], mi[N][M], lg[N], val[N];

int getmax(int l,int r) {
	int k=lg[r-l+1];
	return max(mx[l][k],mx[r-(1<<k)+1][k]);
}

int getmin(int l,int r) {
	int k=lg[r-l+1];
	return min(mi[l][k],mi[r-(1<<k)+1][k]);
}

int solve(int l) {
	m=0;
	up(i,1,n-l+1) val[++m]=getmax(i,i+l-1)-getmin(i,i+l-1);
    nth_element(val+1,val+(m-k+1),val+1+m);
	return val[m-k+1];
}

void mian() {
	cin >> n >> k, t=log2(n), len=n-k+1;
	up(i,1,n) cin >> a[i], mx[i][0]=mi[i][0]=a[i], lg[i]=log2(i);
	up(j,1,t) up(i,1,n-(1<<j)+1) {
		mx[i][j]=max(mx[i][j-1],mx[i+(1<<j-1)][j-1]);
		mi[i][j]=min(mi[i][j-1],mi[i+(1<<j-1)][j-1]);
	}
	int l=1, r=n-k+1, p, ans=solve(len);
	while(l<=r) {
		int mid=(l+r)>>1;
		if(solve(mid)==ans) p=mid, r=mid-1;
		else l=mid+1;
	}
	cout << ans << ' ' << p << '\n';
}

signed main() {
	freopen("sign.in","r",stdin);
	freopen("sign.out","w",stdout); 
	ios::sync_with_stdio(0);
	cin.tie(0);
	cin >> T;
	while(T--) mian();
	return 0;
}

爬山游戏climb

对于每一个 \(x\),考虑存不存在必胜的 \(y\),分类讨论即可,相互干扰的地方需要讨论一下奇偶性,懒得赘述惹。

#include<bits/stdc++.h>
#define int long long
#define up(i,l,r) for(int i=l; i<=r; ++i)
#define dn(i,r,l) for(int i=r; i>=l; --i)
#define pb push_back

using namespace std;

const int N=100005;

int T, n, a[N], lwl[N], lwr[N], upl[N], upr[N], pre[N], suf[N];
vector<int> ans;

void mian() {
	ans.clear();
	cin >> n;
	up(i,1,n) cin >> a[i];
	up(i,1,n) {
		lwl[i]=(i>1&&a[i-1]<a[i])?lwl[i-1]:i;
		upl[i]=(i>1&&a[i-1]>a[i])?upl[i-1]:i;
	}
	dn(i,n,1) {
		lwr[i]=(i<n&&a[i+1]<a[i])?lwr[i+1]:i;
		upr[i]=(i<n&&a[i+1]>a[i])?upr[i+1]:i;
	}
	up(i,1,n) pre[i]=suf[i]=max(i-upl[i],upr[i]-i);
	up(i,1,n) pre[i]=max(pre[i-1],pre[i]);
	dn(i,n,1) suf[i]=max(suf[i+1],suf[i]);
	up(i,1,n) {
		int l=lwl[i], r=lwr[i];
		bool flag=max(pre[l-1],suf[r+1])>=max(i-l,r-i);
		if((i-l+1)%2==0) flag|=max(l-upl[l],upr[l]-l)>=(r-i);
		else {
			flag|=(i-l<=l-lwl[l])&&(r-i<=max(i-l,l-upl[l]));
			flag|=(i-l-1>=r-i);
		}
		if((r-i+1)%2==0) flag|=max(r-upl[r],upr[r]-r)>=(i-l);
		else {
			flag|=(r-i<=upr[r]-r)&&(i-l<=max(r-i,upr[r]-r));
			flag|=(r-i-1>=i-l);
		}
		if(!flag) ans.pb(i);
	}
	cout << ans.size() << ' ';
	for(int i:ans) cout << i << ' ';
	cout << '\n';
}

signed main() {
	freopen("climb.in","r",stdin);
	freopen("climb.out","w",stdout); 
	ios::sync_with_stdio(0);
	cin.tie(0);
	cin >> T;
	while(T--) mian();
	return 0;
}

旅行travel

为了方便不妨先考虑 \(k=1\) 的点集 \(p=\{x_i,y_i\}\) 还有总位移,然后会出现的点就是 \((x_i+t\Delta x,y_i+t\Delta y)\)

我们对于 \(i\) 考虑 \((x_i+t\Delta x,y_i+t\Delta y)\) 的合法性。首先要跟别的 \(i’\) 去重,重复的点出现的形式显然是 \(l/r\) 秒前/后的 \(i'\) 会出现,比如 \((x_i,y_i)=(x_j+r\Delta x,y_j+r\Delta y)\),要求 \(r=\frac{x_i-x_j}{\Delta x}=\frac{y_i-y_j}{\Delta y}\),按照 \(x\mod \Delta x,x\Delta y-y\Delta x\) 分类同类里面有贡献,找 \(l/r\) 就相当于找同类更小/大的 \(x_{i'}\)。不妨钦定 \(i\) 是第一个出现的,那么要求未来不会出现,就是 \(t=k-\max r,\dots k-1\)。之后考虑 \((x'(+1),y'(+1))\) 的存在性,还是先查询一个 \(l/r\) 秒前/后会出现,合法的 \(t\) 至少满足 \(t\geq l\) 或者 \(t\leq k-1-r\)。做一个区间取并即可,想要好些一点可以离散化区间起点然后暴力判断。

#include<bits/stdc++.h>
#define int long long
#define up(i,l,r) for(int i=l; i<=r; ++i)
#define dn(i,r,l) for(int i=r; i>=l; --i)
#define pii pair<int,int>
#define mp make_pair
#define pb push_back
#define x first
#define y second

using namespace std;

const int N=100005, inf=2e9;

int T, n, k, X, Y, Ans, sp[N], tot;
pii a[N];
char str[N];
map<pii,set<int> > qur;

pii get(int x,int y) {
	pii u=mp((x%X+X)%X,x*Y-y*X);
	if(Y==0) u.second=y;
	auto L=qur[u].upper_bound(x);
	auto R=qur[u].lower_bound(x);
	pii res=mp(inf,inf);
	if(L!=qur[u].begin()) res.second=(x-*--L)/abs(X);
	if(R!=qur[u].end()) res.first=(*R-x)/abs(X);
	return res; 
}

void add(int x,int y,int v) {
	pii u=mp((x%X+X)%X,x*Y-y*X);
	if(Y==0) u.second=y;
	if(v==1) qur[u].insert(x); else qur[u].erase(x);
}

void mian() {
	qur.clear(), Ans=0;
	cin >> n >> k >> (str+1);
	up(i,1,n) {
		a[i]=a[i-1];
		if(str[i]=='E') ++a[i].x;
		if(str[i]=='N') ++a[i].y;
		if(str[i]=='W') --a[i].x;
		if(str[i]=='S') --a[i].y;
	}
    X=a[n].x, Y=a[n].y, a[++n]=mp(0,0);
	sort(a+1,a+1+n), n=unique(a+1,a+1+n)-a-1;
	if(X<0) { X=-X; up(i,1,n) a[i].x=-a[i].x; }
	if(X==0) { swap(X,Y); up(i,1,n) swap(a[i].x,a[i].y); }
	if(X==0) {
		map<pii,int> chk;
		up(i,1,n) chk[a[i]]=1;
		up(i,1,n) if(chk[mp(a[i].x+1,a[i].y)]&&chk[mp(a[i].x,a[i].y+1)]&&chk[mp(a[i].x+1,a[i].y+1)]) ++Ans;
		cout << Ans << '\n';
		return;
	}
	up(i,1,n) add(a[i].x,a[i].y,1);
	up(i,1,n) {
		add(a[i].x,a[i].y,-1);
		int L=get(a[i].x,a[i].y).second, R=k-1;
		if(L==inf||L>k) L=0; else L=k-L;
		add(a[i].x,a[i].y,+1);
		pii x=get(a[i].x+1,a[i].y), y=get(a[i].x,a[i].y+1), z=get(a[i].x+1,a[i].y+1);
		sp[tot=0]=0, sp[++tot]=L, sp[++tot]=R+1;
		sp[++tot]=x.x, sp[++tot]=R-x.y+1;
		sp[++tot]=y.x, sp[++tot]=R-y.y+1;
		sp[++tot]=z.x, sp[++tot]=R-z.y+1;
		sort(sp+1,sp+1+tot), tot=unique(sp+1,sp+1+tot)-sp-1;
		up(i,1,tot-1) {
			if(sp[i]<L||sp[i+1]-1>R) continue;
			int u=sp[i];
			if((x.x<=u||x.y<=R-u)&&(y.x<=u||y.y<=R-u)&&(z.x<=u||z.y<=R-u)) Ans+=sp[i+1]-sp[i];
		}
	}
	cout << Ans << '\n';
}

signed main() {
	freopen("travel.in","r",stdin);
	freopen("travel.out","w",stdout); 
	ios::sync_with_stdio(0);
	cin.tie(0);
	cin >> T;
	while(T--) mian();
	return 0;
}

排列permutation

先组合意义一下,一组 \(p\) 的贡献相当于 \(a_i\leq p_{j,i}\)\(a\) 的数量,所以想办法 dp 一下对于 \(a\) 有多少组合法的 \(p\),答案就是所有 \(a\) 的计数加起来。考虑一下 \(a\) 确定的时候怎么做,填写一个 \(p_{i,j}\) 的时候关心 \(a_i\),那么初始有 \(n-a_i+1\) 种填法,那还关心以前填了多少个 \(\geq a_i\) 的数量。非常经典又显然的可以考虑按照 \(a\downarrow\) 填写,填法就是 \(n-a_i+1-pre\)

放到序列上看看怎么做,关心哪些列填写了以及现在要填写的值,状压所有不太实际,但是因为不用钦定的列等价可以 \(2^{10}\) 状压哪些要被钦定的列被填写了、 再记录有多少不被钦定的列被填写了。转移的话先虑多填写几列不被钦定的列,然后还要同层转移钦定的列的填写,同层顺序转移即可。

诶呀怎么说的这么少,有的人写的时候可不是这样的轻松 /fad

#define _CRT_SECURE_NO_WARNINGS
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
#pragma GCC optimize("-fgcse")
#pragma GCC optimize("-fgcse-lm")
#pragma GCC optimize("-fipa-sra")
#pragma GCC optimize("-ftree-pre")
#pragma GCC optimize("-ftree-vrp")
#pragma GCC optimize("-fpeephole2")
#pragma GCC optimize("-ffast-math")
#pragma GCC optimize("-fsched-spec")
#pragma GCC optimize("unroll-loops")
#pragma GCC optimize("-falign-jumps")
#pragma GCC optimize("-falign-loops")
#pragma GCC optimize("-falign-labels")
#pragma GCC optimize("-fdevirtualize")
#pragma GCC optimize("-fcaller-saves")
#pragma GCC optimize("-fcrossjumping")
#pragma GCC optimize("-fthread-jumps")
#pragma GCC optimize("-funroll-loops")
#pragma GCC optimize("-fwhole-program")
#pragma GCC optimize("-freorder-blocks")
#pragma GCC optimize("-fschedule-insns")
#pragma GCC optimize("inline-functions")
#pragma GCC optimize("-ftree-tail-merge")
#pragma GCC optimize("-fschedule-insns2")
#pragma GCC optimize("-fstrict-aliasing")
#pragma GCC optimize("-fstrict-overflow")
#pragma GCC optimize("-falign-functions")
#pragma GCC optimize("-fcse-skip-blocks")
#pragma GCC optimize("-fcse-follow-jumps")
#pragma GCC optimize("-fsched-interblock")
#pragma GCC optimize("-fpartial-inlining")
#pragma GCC optimize("no-stack-protector")
#pragma GCC optimize("-freorder-functions")
#pragma GCC optimize("-findirect-inlining")
#pragma GCC optimize("-fhoist-adjacent-loads")
#pragma GCC optimize("-frerun-cse-after-loop")
#pragma GCC optimize("inline-small-functions")
#pragma GCC optimize("-finline-small-functions")
#pragma GCC optimize("-ftree-switch-conversion")
#pragma GCC optimize("-foptimize-sibling-calls")
#pragma GCC optimize("-fexpensive-optimizations")
#pragma GCC optimize("-funsafe-loop-optimizations")
#pragma GCC optimize("inline-functions-called-once")
#pragma GCC optimize("-fdelete-null-pointer-checks")

#include<bits/stdc++.h>
#define int long long
#define up(i,l,r) for(int i=l; i<=r; ++i)
#define dn(i,r,l) for(int i=r; i>=l; --i)

using namespace std;

const int N=55, M=11, P=998244353;

int id, T, n, m, k, x[M], y[M], xt, len, yh[N][N], tag[N][N], sum[N][N];
int range[N][1<<M][N], Range[N][1<<M][N], sigma[N][1<<M][N];
int rx[M], ry[M], w[M], f[N][N][1<<M], popcnt[1<<M], msk[N], inv[N], coef[N][N][N][M];

inline void add(int &a,int b) { a=(a+b)%P; }
inline void mul(int &a,int b) { a=a*b%P; }
inline int C(int n,int m) { return (m<0||n<m)?0:yh[n][m]; }

inline int ksm(int a,int b=P-2) {
	int ret=1;
	for( ; b; b>>=1) {
		if(b&1) ret=ret*a%P;
		a=a*a%P;
	}
	return ret;
}

void mian() {
	xt=len=0;
	memset(tag,0,sizeof(tag));
	memset(sum,0,sizeof(sum));
	memset(f,0,sizeof(f));
	memset(popcnt,0,sizeof(popcnt));
	memset(msk,0,sizeof(msk));
	cin >> n >> m >> k;
	up(i,1,k) {
		cin >> rx[i] >> ry[i] >> w[i];
		x[++xt]=rx[i], y[++len]=ry[i];
	}
	sort(x+1,x+1+xt), xt=unique(x+1,x+1+xt)-x-1;
	sort(y+1,y+1+len), len=unique(y+1,y+1+len)-y-1;
	up(i,1,n) inv[i]=ksm(i,m-xt);
	up(i,1,k) {
		rx[i]=lower_bound(x+1,x+1+xt,rx[i])-x;
		ry[i]=lower_bound(y+1,y+1+len,ry[i])-y;
		tag[rx[i]][ry[i]]=w[i], sum[rx[i]][w[i]]=1, msk[rx[i]]|=(1<<ry[i]-1);
	}
	up(i,1,k) up(j,1,i-1) if(w[i]==w[j]&&rx[i]==rx[j]) { cout << 0 << '\n'; return; }
	up(i,1,xt) dn(j,n,1) sum[i][j]=sum[i][j+1]+1-sum[i][j];
	up(i,1,(1<<len)-1) popcnt[i]=popcnt[i&(i-1)]+1;
	f[0][0][0]=1;
	up(i,1,n) up(j,0,n-len) up(d,0,n-len-j) up(ps,0,len) {
		coef[i][j][d][ps]=1;
		up(u,j+1,j+d) mul(coef[i][j][d][ps],inv[max(0ll,(n-i+1)-(n-ps-u))]);
	}
	up(i,1,n) up(s,0,(1<<len)-1) {
		range[i][s][0]=Range[i][s][0]=1;
		up(u,1,n-len) {
			range[i][s][u]=range[i][s][u-1];
			sigma[i][s][u]=sigma[i][s][u-1];
			up(p,1,xt) {
				int val=max(0ll,sum[p][i]-(sum[p][1]-u-popcnt[s]+popcnt[msk[p]&s]));
				mul(range[i][s][u],max(val,1ll));
				add(sigma[i][s][u],val==0);
			}
			Range[i][s][u]=ksm(range[i][s][u]);
		}
	}
	up(i,1,n) {
		up(j,0,n-len) up(s,0,(1<<len)-1) up(d,0,n-len-j) {
			int val=C(n-len-j,d)*coef[i][j][d][popcnt[s]]%P;
			if(sigma[i][s][j+d]-sigma[i][s][j]) val=0;
			else (val*=range[i][s][j+d]*Range[i][s][j]%P)%=P,
			add(f[i][j+d][s],f[i-1][j][s]*val%P);
		}
		up(u,1,len) up(j,0,n-len) up(s,0,(1<<len)-1) {
			if(s>>(u-1)&1) continue;
			int val=inv[max(0ll,(n-i+1)-(n-j-popcnt[s]-1))];
			up(p,1,xt) {
				if(tag[p][u]) val*=(tag[p][u]>=i);
				else mul(val,max(0ll,sum[p][i]-(sum[p][1]-j-1-popcnt[s]+popcnt[msk[p]&s])));
			} 
			add(f[i][j][s+(1<<u-1)],f[i][j][s]*val%P);
		}
	}
	cout << f[n][n-len][(1<<len)-1] << '\n';
}

signed main() {
	freopen("permutation.in","r",stdin);
	freopen("permutation.out","w",stdout); 
	ios::sync_with_stdio(0);
	cin.tie(0);
	up(i,0,50) {
		yh[i][0]=yh[i][i]=1;
		up(j,1,i-1) yh[i][j]=(yh[i-1][j-1]+yh[i-1][j])%P; 
	}
	cin >> id >> T;
	while(T--) mian();
	return 0;
}
posted @ 2025-10-14 16:19  Hypoxia571  阅读(11)  评论(0)    收藏  举报