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
",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
",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
",ans);
else printf("-1
");
}
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
",ansl+1,ansr);
} else printf("-1
");
}