2/19 福建四校联考
1.設計圖案
給你一個n*m的矩陣,每個格子必須填或者不能填,要用環和1*2的小方塊填滿它,求方案數。
比如3*2,每個格子都必須填 有6種填法。
n*m<=300??
當時一看就覺得不可做然后就放棄了.....
題解:有個結論:
?
?
狀壓dp詳細就是:
按照從上到下,從左到右dp,用f[i][j][k]表示到第i行j列的格子,輪廓線之上的格子的狀態是k的方案數量。
如果這個格子不能填,那么他上面的格子必須被填滿,上面格子也被填了的時候f[i][j][k]=f[i][j-1][k](j!=1)或者f[i-1][m][k](j=1)
如果這個格子可以填,那么先看一下它上面那個格子是否填滿了,沒填滿就一定要填,填滿了就不能豎著填了。然后看一下能不能橫著填就可以了。
設x=2^(j-1)?? f[i][j][k^x]+=f[i][j-1][k](j!=1) 或者f[i-1][m][k](j==1)??? 這句話表示的是填豎著的。
當j!=1時,判斷一下是否可以橫著填,可以的時候f[i][j][k|(x<<1)]+=f[i][j-1][k]
復雜度 nm * 2^(min(n,m))
實際實現可以滾動數組,這樣簡單很多。
代碼
#include<iostream> #include<cstdio> #define ll long long #include<cstring> 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*10+ch-'0'; ch=getchar();}return x*f; } int n,m,mod; ll f[2][1<<17]; bool b[305][305]; bool b2[305][305];int main() {freopen("design.in","r",stdin);freopen("design.out","w",stdout);n=read();m=read();mod=read();for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)b[i][j]=(bool)read();if(n<m){for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)b2[i][j]=b[i][j];swap(n,m);for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)b[i][j]=b2[j][i];}int nown=1,pre=0,to=(1<<m)-1;f[pre][to]=1;for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){for(int k=0;k<=to;k++){int x=1<<j-1;if(!b[i][j]){if((k|x)==k) f[nown][k]=(f[nown][k]+f[pre][k])%mod; } else{f[nown][k^x]=(f[nown][k^x]+f[pre][k])%mod; if(j!=1&&(k|x)==k&&((k|(x>>1))!=k)&&b[i][j-1])f[nown][k|(x>>1)]=(f[nown][k|(x>>1)]+f[pre][k])%mod;} }pre=1-pre;nown=1-nown;memset(f[nown],0,sizeof(f[nown])); } }ll ans=(f[pre][to]*f[pre][to])%mod; printf("%lld\n",ans);return 0; }?
?2.最優發射
大意:有一個環,有n個武器,每個武器可以打死一個區間內的人。
多組數據,每次給你很多人,問至少要多少個武器可以全部打死.....
n<=100000? 人的總數<=200000
題解做法:
倍增加速貪心。
我的做法:
先刪掉沒用的邊,這樣的話就可以保證邊的l和r都是遞增的。由于數據組數比較多,所以顯然不能每次遍歷全部邊。每個點直接二分一個能蓋住它的邊中最右能到哪里。
不考慮環,顯然是一個dp,可以優化到nlogn??
但是加上環之后就比較麻煩,可以用一個lct維護一下dp路徑
從1到m遍歷,從每一個點向它能轉移的點連邊,如果它能越過環,就向m+1連邊,這樣的話一個點的深度就是它一直到現在的點的dp值。
每個點如果有能跨過環的邊,那么就用能跨到的地方右邊的第一個點的深度+1更新一下答案。
復雜度nlogn
現場的時候寫掛了只有60.
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #define INF 2000000000 #define ms(x) memset(x,0,sizeof(x)) 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*10+ch-'0'; ch=getchar();}return x*f; } int n,m,L,qq,ans; int t[400005]; int c[200005][2]; int fa[200005],size[200005]; int rev[200005]; int qu[200005],top=0; int tf[200005]; bool yes;struct line{int l,r; }ll[400005];bool cmp(line x,line y) {return (x.l<y.l)||(x.l==y.l&&x.r>y.r); }inline bool isroot(int x){return c[fa[x]][0]!=x&&c[fa[x]][1]!=x;} inline void update(int x){size[x]=size[c[x][0]]+size[c[x][1]]+1;}void rotate(int x) {//printf("rotate%d\n",x);int y=fa[x],z=fa[y],l,r;l=(c[y][1]==x),r=l^1;if(!isroot(y)) c[z][c[z][1]==y]=x;fa[x]=z;fa[y]=x;fa[c[x][r]]=y;c[y][l]=c[x][r];c[x][r]=y;update(y);update(x); }void splay(int x) {while(!isroot(x)){int y=fa[x],z=fa[y];if(!isroot(y)){if(c[z][1]==y^c[y][1]==x)rotate(x);else rotate(y);}rotate(x);} }void access(int x) {splay(x);while(fa[x]){int y=fa[x];splay(y);c[y][1]=x;update(y);splay(x);} } void link(int x,int y) {access(x);splay(x);//rever(c[x][0]); access(y);splay(y);c[y][1]=x;fa[x]=y; }void cut(int x) {access(x);splay(x);fa[c[x][0]]=0;c[x][0]=0; }int get(int x) {int l=1,r=n,mid,ans=-1;while(l<=r){mid=(l+r)>>1;if(ll[mid].l>x) r=mid-1;else{ ans=ll[mid].r;l=mid+1; } }return ans; }int get2(int x) {int l=1,r=m,mid,ans=0;while(l<=r){mid=(l+r)>>1;if(t[mid]<=x) {ans=mid;l=mid+1;}else {r=mid-1;}}return ans; }int check(int x) {access(x);//splay(x);return size[c[x][0]]; }int main() {freopen("launch.in","r",stdin);freopen("launch.out","w",stdout);n=read();qq=read();L=read();for(int i=1;i<=n;i++){ll[i].l=read();ll[i].r=read();if(ll[i].r<ll[i].l) ll[i].r+=L;}for(int i=1;i<=n;i++) if(ll[i].r>=L) {ll[++n].l=0;ll[n].r=ll[i].r-L; }sort(ll+1,ll+n+1,cmp);int j=1;for(int i=2;i<=n;i++){if(ll[i].r>ll[j].r) {ll[++j]=ll[i];} } n=j; // for(int i=1;i<=n;i++) printf("%d %d %d\n",i,ll[i].l,ll[i].r);while(qq--){ms(fa);ms(c);ms(size);ms(rev);t[0]=-1;yes=true;m=read();for(int i=1;i<=m;i++) t[i]=read();sort(t+1,t+m+1);ans=INF;size[m+1]=1;int j=1;for(int i=2;i<=m;i++)if(t[i]!=t[j]) t[++j]=t[i];m=j;for(int i=0;i++<=m;i++) size[i]=1;if(yes) for(int i=1;i<=m;i++){int x=get(t[i]);if(x==-1||x<t[i]) {puts("-1");yes=false;break;}if(x-L>=t[1]){ ans=min(ans,check(get2(x-L)+1)+1);link(i,m+1);}else link(i,get2(x)+1);}ans=min(ans,check(1));if(yes) printf("%d\n",ans);}return 0; }?
?3.傳輸網絡
有m條信息,n個傳輸裝置。
每個裝置可以把一個范圍a-b內的全部信息轉移到c(a<=c<=b),但是需要d點費用
現在要把全部信息都轉移到一個點,求最小費用。
m<=10^9 n<=10^5
先離散一下,再用兩個線段樹維護第一條和最后一條信息到每個點c的距離。
然后按dp做就行了。
現場只寫了n^3 dp 只有50分......
#include<iostream> #include<cstdio> #include<algorithm> #define ll long long #define N 262144 #define INF 1000000000000000000LL using namespace std; inline ll llread() {ll 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*10+ch-'0'; ch=getchar();}return x*f; } 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*10+ch-'0'; ch=getchar();}return x*f; } int n,m,cnt=0; ll ans=INF; int s[300005]; struct ma{int l,r,c;ll d; }a[100005];ll T1[600005],T2[600005];ll query(ll*T,int l,int r) {ll minn=INF;for(l+=N-1,r+=N+1;l^r^1;l>>=1,r>>=1){if(~l&1) minn=min(minn,T[l+1]);if( r&1) minn=min(minn,T[r-1]); }return minn; }void renew(ll*T,int x,ll ad) {T[x+=N]=min(T[x],ad);for(x>>=1;x;x>>=1)T[x]=min(T[x<<1],T[(x<<1)+1]); } void init() {for(int i=1;i<=N*2;i++)T1[i]=T2[i]=INF; }int main() {freopen("network.in","r",stdin);freopen("network.out","w",stdout);n=read();m=read();for(int i=1;i<=n;i++){a[i].l=read();a[i].r=read();a[i].c=s[i]=read();a[i].d=llread();}s[n+1]=1;s[n+2]=m;sort(s+1,s+n+3);init();int j=0;for(int i=1;i<=n+2;i++){if(s[i]!=s[i-1])s[++j]=s[i];}cnt=j;renew(T1,1,0);renew(T2,cnt,0);for(int i=1;i<=n;i++){a[i].l=lower_bound(s+1,s+cnt+1,a[i].l)-s;a[i].r=upper_bound(s+1,s+cnt+1,a[i].r)-s-1;a[i].c=lower_bound(s+1,s+cnt+1,a[i].c)-s;}for(int i=1;i<=n;i++){if(a[i].l>a[i].r||a[i].l>cnt||a[i].r>cnt) continue;ll x1=query(T1,a[i].l,a[i].r);ll x2=query(T2,a[i].l,a[i].r);ans=min(ans,x1+x2+a[i].d);renew(T1,a[i].c,x1+a[i].d);renew(T2,a[i].c,x2+a[i].d); }if(ans<INF) printf("%lld\n",ans);else puts("-1");return 0; }?
轉載于:https://www.cnblogs.com/FallDream/p/liankao219.html
總結
以上是生活随笔為你收集整理的2/19 福建四校联考的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: php拼接二维码,文字和二维码进行合并
- 下一篇: 18-Flutter移动电商实战-首页_