<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      【做題記錄】csp2025-狀壓dp

      A. [USACO13NOV] No Change G
      \(dp[S]\) 表示取的硬幣狀態為 \(S\) 時最多買多少東西。給 \(n\) 個物品做前綴和,轉移二分即可。時間復雜度 \(O(2^kk\log n)\)

      Code
      #include<bits/stdc++.h>
      #define ll long long
      #define il inline
      #define read(x){\
      	char ch;\
      	int fu=1;\
      	while(!isdigit(ch=getchar()))\
      		fu-=(ch=='-')<<1;\
      	x=ch&15;\
      	while(isdigit(ch=getchar()))\
      		x=(x<<1)+(x<<3)+(ch&15);\
      	x*=fu;\
      }
      #define int ll
      #define uprb upper_bound
      using namespace std;
      namespace asbt{
      namespace cplx{bool begin;}
      const int maxn=1e5+5,maxm=(1<<16)+5;
      int n,m,a[20],b[maxn],dp[maxm];
      namespace cplx{
      	bool end;
      	il double usdmem(){return (&begin-&end)/1048576.0;}
      }
      signed main(){
      	read(m)read(n);
      	for(int i=1;i<=m;i++){
      		read(a[i]);
      	}
      	for(int i=1;i<=n;i++){
      		read(b[i]);
      		b[i]+=b[i-1];
      	}
      	int ans=-1;
      	for(int S=0;S<1<<m;S++){
      		int tmp=0;
      		for(int i=1;i<=m;i++){
      			if(S>>(i-1)&1){
      				continue;
      			}
      			tmp+=a[i];
      			int nS=S|1<<(i-1);
      			int p=uprb(b+1,b+n+1,b[dp[S]]+a[i])-b-1;
      			dp[nS]=max(dp[nS],p);
      		}
      		if(dp[S]==n){
      			ans=max(ans,tmp);
      		}
      	}
      	printf("%lld",ans);
      	return 0;
      }
      }
      signed main(){return asbt::main();}
      

      B. [HAOI2007] 修筑綠化帶
      好好好,根本不是狀壓DP……
      思路像理想的正方形。考慮對于一個固定的 \(A\times B\) 的矩形,答案一定是矩形的和減去它里面最小的 \(C\times D\) 的矩形的和。前者二維前綴和即可,后者需要類似于那道題搞兩次單調隊列。
      具體地,設 \(B[i][j]\) 表示以 \((i,j)\) 為右下角的 \(C\times D\) 的矩形的和,設 \(P[i][j]\) 表示以 \((i,j)\) 為右下角的 \(A\times B\) 的矩形中,右下角和 \((i,j)\) 在同一行的 \(C\times D\) 的所有矩形中最小的一個。這需要跑一次單調隊列。然后再對 \(P\) 類似地縱向求一次單調隊列得到 \(Q\)\(Q\) 即為所求。
      需要注意這樣一句話:

      同時在花壇四周修建一片綠化帶,讓花壇被綠化帶圍起來。

      也就是說,花壇是不能貼著綠化帶的邊的。

      Code
      #include<bits/stdc++.h>
      #define ll long long
      #define il inline
      #define read(x){\
      	char ch;\
      	int fu=1;\
      	while(!isdigit(ch=getchar()))\
      		fu-=(ch=='-')<<1;\
      	x=ch&15;\
      	while(isdigit(ch=getchar()))\
      		x=(x<<1)+(x<<3)+(ch&15);\
      	x*=fu;\
      }
      using namespace std;
      namespace asbt{
      namespace cplx{bool begin;}
      const int maxn=1e3+5,inf=0x3f3f3f3f;
      typedef int juz[maxn][maxn];
      int n,m,a,b,c,d,q[maxn];
      juz f,A,B,P,Q;
      il int sum(int x1,int y1,int x2,int y2){
      	return f[x2][y2]-f[x1-1][y2]-f[x2][y1-1]+f[x1-1][y1-1];
      }
      namespace cplx{
      	bool end;
      	il double usdmem(){return (&begin-&end)/1048576.0;}
      }
      int main(){
      	read(n)read(m)read(a)read(b)read(c)read(d);
      	memset(A,-0x3f,sizeof A);
      	memset(B,0x3f,sizeof B);
      	for(int i=1;i<=n;i++){
      		for(int j=1;j<=m;j++){
      			read(f[i][j]);
      			f[i][j]+=f[i-1][j]+f[i][j-1]-f[i-1][j-1];
      			if(i>=a&&j>=b){
      				A[i][j]=sum(i-a+1,j-b+1,i,j);
      			}
      			if(i>=c&&j>=d){
      				B[i][j]=sum(i-c+1,j-d+1,i,j);
      			}
      		}
      	}
      //	for(int i=1;i<=n;i++){
      //		for(int j=1;j<=m;j++){
      //			cout<<A[i][j]<<" ";
      //		}
      //		puts("");
      //	}
      //	for(int i=1;i<=n;i++){
      //		for(int j=1;j<=m;j++){
      //			cout<<B[i][j]<<" ";
      //		}
      //		puts("");
      //	}
      	memset(P,0x3f,sizeof P);
      	for(int i=1,hd,tl;i<=n;i++){
      		hd=1,tl=0;
      		q[1]=0;
      		for(int j=1;j<=m;j++){
      			while(hd<=tl&&q[hd]<j-b+d+1){
      				hd++;
      			}
      			P[i][j]=B[i][q[hd]];
      			while(hd<=tl&&B[i][q[tl]]>B[i][j]){
      				tl--;
      			}
      			q[++tl]=j;
      		}
      	}
      	memset(Q,0x3f,sizeof Q);
      	for(int j=1,hd,tl;j<=m;j++){
      		hd=1,tl=0;
      		q[1]=0;
      		for(int i=1;i<=n;i++){
      			while(hd<=tl&&q[hd]<i-a+c+1){
      				hd++;
      			}
      			Q[i][j]=P[q[hd]][j];
      			while(hd<=tl&&P[q[tl]][j]>P[i][j]){
      				tl--;
      			}
      			q[++tl]=i;
      		}
      	}
      	int ans=-inf;
      	for(int i=1;i<=n;i++){
      		for(int j=1;j<=m;j++){
      			ans=max(ans,A[i][j]-Q[i][j]);
      		}
      	}
      	printf("%d",ans);
      	return 0;
      }
      }
      int main(){return asbt::main();}
      

      C. [COCI2016-2017#1] Vje?tica
      6,其實很簡單。
      考慮將兩個字符串集合合并時,新的集合的答案,其實就是兩個集合的答案之和再減去公共的字符數量。
      原因是新的公共字符構成的集合絕對是舊的公共字符集合的子集,換句話說一定能覆蓋。于是轉移是簡單的。
      轉移一定要枚舉每個子集,原因是簡單地加入一個字符串是沒有覆蓋所有情況的。

      Code
      #include<bits/stdc++.h>
      #define ll long long
      #define il inline
      #define read(x){\
      	char ch;\
      	int fu=1;\
      	while(!isdigit(ch=getchar()))\
      		fu-=(ch=='-')<<1;\
      	x=ch&15;\
      	while(isdigit(ch=getchar()))\
      		x=(x<<1)+(x<<3)+(ch&15);\
      	x*=fu;\
      }
      using namespace std;
      namespace asbt{
      namespace cplx{bool begin;}
      const int maxn=1e6+5,maxm=(1<<16)+5,inf=0x3f3f3f3f;
      int n,cnt[20][30],dp[maxm],hp[30];
      char s[maxn];
      namespace cplx{
      	bool end;
      	il double usdmem(){return (&begin-&end)/1048576.0;}
      }
      int main(){
      	read(n);
      	memset(dp,0x3f,sizeof dp);
      	for(int i=1;i<=n;i++){
      		scanf(" %s",s+1);
      		int S=1<<(i-1);
      		dp[S]=1;
      		for(int j=1;s[j]!='\0';j++){
      			cnt[i][s[j]-'a']++;
      			dp[S]++;
      		}
      	}
      	for(int S=1;S<1<<n;S++){
      		for(int i=0;i<=25;i++){
      			hp[i]=inf;
      		}
      		for(int i=1;i<=n;i++){
      			if(S>>(i-1)&1){
      				for(int j=0;j<=25;j++){
      					hp[j]=min(hp[j],cnt[i][j]);
      				}
      			}
      		}
      		int tmp=1;
      		for(int i=0;i<=25;i++){
      			tmp+=hp[i];
      		}
      		for(int nS=S&(S-1);nS;nS=(nS-1)&S){
      			dp[S]=min(dp[S],dp[nS]+dp[S^nS]-tmp);
      		}
      	}
      	printf("%d",dp[(1<<n)-1]);
      	return 0;
      }
      }
      int main(){return asbt::main();}
      

      D. New Year Tree
      一眼線段樹。
      具體地,先跑一遍dfn,然后維護區間顏色集合。
      顯然它又不是狀壓DP
      記得1ll

      Code
      #include<bits/stdc++.h>
      #define ll long long
      #define il inline
      #define read(x){\
      	char ch;\
      	int fu=1;\
      	while(!isdigit(ch=getchar()))\
      		fu-=(ch=='-')<<1;\
      	x=ch&15;\
      	while(isdigit(ch=getchar()))\
      		x=(x<<1)+(x<<3)+(ch&15);\
      	x*=fu;\
      }
      #define pb push_back
      #define popcntll __builtin_popcountll
      #define lid id<<1
      #define rid id<<1|1
      using namespace std;
      namespace asbt{
      namespace cplx{bool begin;}
      const int maxn=4e5+5;
      int n,m,a[maxn],cnt;
      int dfn[maxn],sz[maxn],zhan[maxn];
      vector<int> e[maxn];
      il void dfs(int u,int fa){
      	dfn[u]=++cnt;
      	zhan[cnt]=u;
      	sz[u]=1;
      	for(int v:e[u]){
      		if(v==fa){
      			continue;
      		}
      		dfs(v,u);
      		sz[u]+=sz[v];
      	}
      }
      struct stree{
      	int tag[maxn<<2];
      	ll zhi[maxn<<2];
      	il void pushup(int id){
      		zhi[id]=zhi[lid]|zhi[rid];
      	}
      	il void pushdown(int id){
      		if(tag[id]){
      			tag[lid]=tag[rid]=tag[id];
      			zhi[lid]=zhi[rid]=1ll<<(tag[id]-1);
      			tag[id]=0;
      		}
      	}
      	il void build(int id,int l,int r){
      		if(l==r){
      			zhi[id]=1ll<<(a[zhan[l]]-1);
      			return ;
      		}
      		int mid=(l+r)>>1;
      		build(lid,l,mid);
      		build(rid,mid+1,r);
      		pushup(id);
      	}
      	il void upd(int id,int L,int R,int l,int r,int val){
      		if(L>=l&&R<=r){
      			tag[id]=val;
      			zhi[id]=1ll<<(val-1);
      			return ;
      		}
      		pushdown(id);
      		int mid=(L+R)>>1;
      		if(l<=mid){
      			upd(lid,L,mid,l,r,val);
      		}
      		if(r>mid){
      			upd(rid,mid+1,R,l,r,val);
      		}
      		pushup(id);
      	}
      	il ll query(int id,int L,int R,int l,int r){
      		if(L>=l&&R<=r){
      			return zhi[id];
      		}
      		pushdown(id);
      		int mid=(L+R)>>1;
      		ll res=0;
      		if(l<=mid){
      			res|=query(lid,L,mid,l,r);
      		}
      		if(r>mid){
      			res|=query(rid,mid+1,R,l,r);
      		}
      		return res;
      	}
      }SG;
      namespace cplx{
      	bool end;
      	il double usdmem(){return (&begin-&end)/1048576.0;}
      }
      int main(){
      	read(n)read(m);
      	for(int i=1;i<=n;i++){
      		read(a[i]);
      	}
      	for(int i=1,u,v;i<n;i++){
      		read(u)read(v);
      		e[u].pb(v),e[v].pb(u);
      	}
      	dfs(1,0);
      	SG.build(1,1,n);
      	while(m--){
      		int opt,u,x;
      		read(opt)read(u);
      		switch(opt){
      			case 1:{
      				read(x);
      				SG.upd(1,1,n,dfn[u],dfn[u]+sz[u]-1,x);
      				break;
      			}
      			default:{
      				printf("%d\n",popcntll(SG.query(1,1,n,dfn[u],dfn[u]+sz[u]-1)));
      				break;
      			}
      		}
      	}
      	return 0;
      }
      }
      int main(){return asbt::main();}
      

      E. Yet Another Substring Reverse
      因為字符不重復,因此不用考慮它們的排列順序,即翻轉子串就是將兩個不交的子串連到一塊。這里不交既指位置不交又指字符集不交。但顯然字符集不交則一定位置不交。因此只用考慮對每一個字符集處理最大長度。高維前綴最大值即可。

      Code
      #include<bits/stdc++.h>
      #define ll long long
      #define il inline
      #define read(x){\
      	char ch;\
      	int fu=1;\
      	while(!isdigit(ch=getchar()))\
      		fu-=(ch=='-')<<1;\
      	x=ch&15;\
      	while(isdigit(ch=getchar()))\
      		x=(x<<1)+(x<<3)+(ch&15);\
      	x*=fu;\
      }
      using namespace std;
      namespace asbt{
      namespace cplx{bool begin;}
      const int maxn=1e6+5,maxm=(1<<20)+5;
      int n,dp[maxm];
      char s[maxn];
      namespace cplx{
      	bool end;
      	il double usdmem(){return (&begin-&end)/1048576.0;}
      }
      int main(){
      	scanf(" %s",s+1);
      	n=strlen(s+1);
      	for(int i=1;i<=n;i++){
      		for(int j=i,S=0;j;j--){
      			if(S>>(s[j]-'a')&1){
      				break;
      			}
      			S|=1<<(s[j]-'a');
      			dp[S]=i-j+1;
      		}
      	}
      	for(int i=1;i<=20;i++){
      		for(int S=0;S<1<<20;S++){
      			if(S>>(i-1)&1){
      				continue;
      			}
      			dp[S|1<<(i-1)]=max(dp[S|1<<(i-1)],dp[S]);
      		}
      	}
      	int ans=0;
      	for(int S=1;S<=(1<<20)-2;S++){
      		ans=max(ans,dp[S]+dp[((1<<20)-1)^S]);
      	}
      	printf("%d",ans);
      	return 0;
      }
      }
      int main(){return asbt::main();}
      

      F. [TJOI2015]棋盤
      重中之重:

      編號從 \(0\) 開始,即第 \(1\) 行指的是中間那行。

      \(dp[i][S]\) 表示第 \(i\) 行放置棋子狀態為 \(S\) 的方案數。發現時間和空間都無法接受,容易想到矩陣加速。代碼十分好敲。對 \(2^{32}\) 取模這件事情,直接開 unsigned int 自然溢出就行了。時間復雜度 \(O(2^{3m}\log n)\)

      Code
      #include<bits/stdc++.h>
      #define ll long long
      #define il inline
      #define read(x){\
      	char ch;\
      	int fu=1;\
      	while(!isdigit(ch=getchar()))\
      		fu-=(ch=='-')<<1;\
      	x=ch&15;\
      	while(isdigit(ch=getchar()))\
      		x=(x<<1)+(x<<3)+(ch&15);\
      	x*=fu;\
      }
      #define ui unsigned int
      using namespace std;
      namespace asbt{
      namespace cplx{bool begin;}
      const int maxn=(1<<6)+5;
      int n,m,p,q,a[5][10];
      int sta[maxn],stn;
      struct juz{
      	ui mat[maxn][maxn];
      	juz(){
      		for(int i=0;i<1<<m;i++){
      			for(int j=0;j<1<<m;j++){
      				mat[i][j]=0;
      			}
      		}
      	}
      	il ui*operator[](const int &x){
      		return mat[x];
      	}
      	il juz operator*(juz x)const{
      		juz res;
      		for(int i=0;i<1<<m;i++){
      			for(int j=0;j<1<<m;j++){
      				for(int k=0;k<1<<m;k++){
      					res[i][j]+=mat[i][k]*x[k][j];
      				}
      			}
      		}
      		return res;
      	}
      }dp,bas,fnl;
      il juz qpow(juz x,int y){
      	juz res;
      	for(int i=0;i<1<<m;i++){
      		res[i][i]=1;
      	}
      	while(y){
      		if(y&1){
      			res=res*x;
      		}
      		x=x*x,y>>=1;
      	}
      	return res;
      }
      namespace cplx{
      	bool end;
      	il double usdmem(){return (&begin-&end)/1048576.0;}
      }
      int main(){
      	read(n)read(m)read(p)read(q);
      	q++;
      	for(int i=1;i<=3;i++){
      		for(int j=1;j<=p;j++){
      			read(a[i][j]);
      		}
      	}
      	for(int S=0;S<1<<m;S++){
      		for(int i=1;i<=m;i++){
      			if(S>>(i-1)&1){
      				for(int j=1,k;j<=p;j++){
      					if(j==q||!a[2][j]){
      						continue;
      					}
      					k=i-q+j;
      					if(k>=1&&k<=m&&(S>>(k-1)&1)){
      						goto togo1;
      					}
      				}
      			}
      		}
      		sta[++stn]=S;
      		dp[0][S]=1;
      		togo1:;
      	}
      //	cout<<stn<<"\n";
      //	for(int i=1;i<=stn;i++){
      //		cout<<bitset<6>(sta[i])<<"\n";
      //	}
      	for(int x=1;x<=stn;x++){
      		for(int y=1;y<=stn;y++){
      			for(int i=1;i<=m;i++){
      				if(sta[x]>>(i-1)&1){
      					for(int j=1,k;j<=p;j++){
      						if(!a[3][j]){
      							continue;
      						}
      						k=i-q+j;
      						if(k>=1&&k<=m&&(sta[y]>>(k-1)&1)){
      							goto togo2;
      						}
      					}
      				}
      				if(sta[y]>>(i-1)&1){
      					for(int j=1,k;j<=p;j++){
      						if(!a[1][j]){
      							continue;
      						}
      						k=i-q+j;
      						if(k>=1&&k<=m&&(sta[x]>>(k-1)&1)){
      							goto togo2;
      						}
      					}
      				}
      			}
      			bas[sta[x]][sta[y]]=1;
      			togo2:;
      		}
      	}
      	for(int S=0;S<1<<m;S++){
      		fnl[S][0]=1;
      	}
      	printf("%u",(dp*qpow(bas,n-1)*fnl)[0][0]);
      	return 0;
      }
      }
      int main(){return asbt::main();}
      
      posted @ 2024-12-21 17:18  zhangxy__hp  閱讀(92)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 91孕妇精品一区二区三区| 国产在线精品中文字幕| 成人国产精品一区二区网站公司| 人妻夜夜爽天天爽| 午夜国产精品福利一二| 国产jjizz女人多水喷水| 亚洲美女厕所偷拍美女尿尿| 国产99青青成人A在线| 精品日韩色国产在线观看| 亚洲AV无码国产永久播放蜜芽 | 久久精品国产亚洲av天海翼| 亚洲欧洲一区二区精品| 无码一区二区三区久久精品| 亚洲AV美女在线播放啊| 国产福利深夜在线播放| 亚洲欧美不卡高清在线| 亚洲产在线精品亚洲第一站一 | 99久久国产精品无码| 国产360激情盗摄全集| 亚洲av男人电影天堂热app| 久久天堂无码av网站| 色狠狠色婷婷丁香五月| 国产成人av三级在线观看| 国产爆乳乱码女大生Av| 国产激情一区二区三区在线| 欧美黑人又粗又大久久久| 国产精品一区二区色综合| 午夜通通国产精品福利| 亚洲精品国产中文字幕| 天天躁夜夜躁天干天干2020| 狠狠躁夜夜躁人人爽天天bl| 元码人妻精品一区二区三区9| 亚洲a∨国产av综合av下载| 国产精品综合av一区二区| 狠狠做五月深爱婷婷天天综合| 人人澡人摸人人添| 丰满的少妇一区二区三区| 成人福利一区二区视频在线 | 欧美日韩国产亚洲沙发| 凤台县| 久久久久久久久毛片精品|