1008Problem - 6957 (hdu.edu.cn)
题意:求最大的列不递减的矩阵大小
思路:用b[][]记录这个数与上面一个数是不是非递减的,然后遍历每一行,h[]表示这一列往上最长的1,就变成了悬线法求最大面积.
int n,m; int a[N][N],b[N][N]; int l[N],r[N],h[N]; void work() { scanf("%d%d",&n,&m); for(int i=1; i<=n; i++) { for(int j=1; j<=m; j++) { scanf("%d",&a[i][j]); if(i==1)b[i][j] = 1; else b[i][j]=(a[i][j]>=a[i-1][j])?1:0; } } int ans = 0; for(int i=1; i<=n; i++) { for(int j=1; j<=m; j++) { if(i == 1)h[j]=1; else h[j]= b[i][j]==1?h[j]+1:1; l[j] = r[j] = j; } for(int j=1; j<=m; j++) { while(l[j]>1&&h[j]<=h[l[j]-1])l[j] = l[l[j]-1]; } for(int j=m; j>=1; j--) { while(r[j]<m&&h[j]<=h[r[j]+1])r[j] = r[r[j]+1]; } for(int j=1; j<=m; j++) { ans = max(ans,(r[j]-l[j]+1)*h[j]); } } printf("%d\n",ans); }
1009 Problem - 6958 (hdu.edu.cn)
题意:n个点,m条边,问是否能把点分成k组,同一组的点(p,q)之间路径上的最大权值小于等于D,不同组的点(p,q)之间路径上的最大权值大于D,若存在输出最小的D
思路:将权值进行排序,每次将同一边权的边进行合并,那么小于等于当前权值的边都在同一组种,剩下的边都在其他组,如果此时恰好剩下k组,那么答案D就是当前的权值,因为小于等于当前权值的边都相连,在同一组了,其他组之间的边都大于D了.满足题意.
const int N = 1e5 + 50,M = 5e5 + 50; struct node { int u,v,w; } p[M]; int n,m,k; int fa[N]; void init() {for(int i=1; i<=n; i++)fa[i] = i;} bool cmp(node a,node b) {return a.w < b.w;} int find_set(int x) { if(fa[x] != x)fa[x]=find_set(fa[x]); return fa[x]; } void work() { scanf("%d%d%d",&n,&m,&k); init(); for(int i=1; i<=m; i++) { scanf("%d%d%d",&p[i].u,&p[i].v,&p[i].w); } sort(p+1,p+1+m,cmp); int ans = 0; for(int i=1; i<=m; i++) { if(p[i].w != p[i-1].w) { if(n == k) { printf("%d\n",ans); return ; } } int x=find_set(p[i].u),y=find_set(p[i].v); if(x == y)continue; n--; fa[x] = y; ans = p[i].w; } if(n == k)printf("%d\n",ans); else printf("-1\n"); }
1006.01字典树 Problem - 6955 (hdu.edu.cn)
我怎么什么都没学过啊....
贴个代码,有空把字典树题刷了.
const int N = 3e6 + 50,M = 5e5 + 50; int n,k; int a[N]; int tr[N][2],idx; int ed[N]; int maxn,res; int read() { int v = 0,f = 1; char c = getchar(); while(c < 48 || 57 < c) { if(c == '-') f = -1; c = getchar(); } while(48 <= c && c <= 57) v = (v<<3) + v + v + c - 48,c = getchar(); return v * f; } struct trie { void insert(int x,int pos) { int now=0; for(int i=29; i>=0; i--) { int c=(x>>i)&1; if(!tr[now][c]) { tr[now][c]=++idx; ed[idx]=-1; tr[idx][0]=tr[idx][1]=0; } now = tr[now][c]; ed[now]=max(ed[now],pos); } } int find(int x) { int now = 0; for(int i=29; i>=0; i--) { int c=(x>>i)&1; int op=(k>>i)&1; //k的j位是0,那如果存在1,这个前缀就大于k,更新 if(!(op&1)) { if(tr[now][c^1]) res = max(res,ed[tr[now][c^1]]); now=tr[now][c]; } else {//k的第j位是1 now = tr[now][c^1]; } if(now==0)return -1; } return ed[now]; } } tree; void init() { for(int i=0; i<=idx; i++) { tr[i][0]=tr[i][1] = 0; ed[i] = 0; } idx=0; } void work() { n=read(),k=read(); for(int i=1; i<=n; i++) { a[i]=read(); if(i!=1)a[i]^=a[i-1]; } init(); int ansl=-1,ansr=n+1; for(int i=1; i<=n; i++) { res = -1; int p = tree.find(a[i]); if(p != -1)res=max(res,p); if(res > 0 && i - res < ansr - ansl) { ansl = res; ansr = i; } tree.insert(a[i],i); } if(ansl > 0) { printf("%d %d\n",ansl+1,ansr); } else printf("-1\n"); }