洛谷 P1392 取数
在做这道题前,先要会他的弱化版(实际一模一样,只是愚蠢的洛谷评测级别差了一档(睿智如姬无夜))
----------------------------------弱化版---------------------
实际只是把矩阵行数改成两行而已
sol:先排序,后考虑一个序列a[1]+b[1],a[2]+b[1],a[3]+b[1],······,a[n-1]+b[1],a[n]+b[1];
显然对于上一个序列而言 a[1]+b[1]<=a[1]+b[2], a[2]+b[1]<=a[2]+b[2], a[3]+b[1]<=a[4]+b[2]
虽然上面反应的只是以a分成的n个组中a[i]+(b[1]到b[2]到b[3]···到b[n])每组序列严格递增
但是利用小根堆就可以完成要求了每次弹出堆顶元素,在压入弹出元素组别的下一个数
#include <cstdio> #include <algorithm> using namespace std; const int N=100005; int n,a[N],b[N],size=0,to[N]; struct node{int key,id;}heap[N*2]; inline void Up(int x) { while(x>0) { if(heap[x].key<heap[x/2].key) { swap(heap[x],heap[x/2]); x/=2; }else break; }return; } inline void Down(int x) { int y=x*2; while(y<=size) { if(y<size&&heap[y].key>heap[y+1].key)y++; if(heap[x].key>heap[y].key) { swap(heap[x],heap[y]); x=y; y=x*2; }else break; }return; } inline void Insert(int v,int id){heap[++size]=(node){v,id};Up(size);} inline node Top(){return heap[1];} inline void Pop(){swap(heap[1],heap[size]);size--;Down(1);} int main() { int i; node tmp; scanf("%d",&n); for(i=1;i<=n;i++)scanf("%d",&a[i]); for(i=1;i<=n;i++)scanf("%d",&b[i]); sort(a+1,a+n+1); sort(b+1,b+n+1); for(i=1;i<=n;i++){Insert(a[i]+b[1],i);to[i]=1;} for(i=1;i<=n;i++) { tmp=Top(); Pop(); printf("%d ",tmp.key); Insert(a[tmp.id]+b[++to[tmp.id]],tmp.id); }printf("\n"); }
----------------------------------强化版---------------------
这就是对于第一行,和第二行合并,得到新的序列,在用新序列与下一个合并,就解决了
#include <cstdio> #include <algorithm> using namespace std; const int N=1005; int n,m,k,a[2][N],b[N],size=0,to[N]; struct node{int key,id;}heap[N*2]; inline void Up(int x) { while(x) { if(heap[x].key<heap[x/2].key) { swap(heap[x],heap[x/2]); x/=2; }else break; }return; } inline void Down(int x) { int y=x*2; while(y<=size) { if(y<size&&heap[y].key>heap[y+1].key)y++; if(heap[x].key>heap[y].key) { swap(heap[x],heap[y]); x=y; y=x*2; }else break; }return; } inline void Insert(int key,int id){heap[++size]=(node){key,id};Up(size);} inline node Top(){return heap[1];} inline void Pop(){swap(heap[1],heap[size]);size--;Down(1);} int main() { int i,j,t=0; node tmp; scanf("%d%d%d",&n,&m,&k); for(i=1;i<=m;i++)scanf("%d",&a[t][i]); sort(a[t]+1,a[t]+m+1); for(i=2;i<=n;i++) { t^=1; for(j=1;j<=m;j++)scanf("%d",&b[j]); sort(b+1,b+m+1); size=0; for(j=1;j<=k;j++) { Insert(a[t^1][j]+b[1],j); to[j]=1; } for(j=1;j<=k;j++) { tmp=Top(); Pop(); a[t][j]=tmp.key; Insert(a[t^1][tmp.id]+b[++to[tmp.id]],tmp.id); } }for(i=1;i<=k;i++)printf("%d ",a[t][i]); }
河田は河田、赤木は赤木……。
私は誰ですか。教えてください、私は誰ですか。
そうだ、俺はあきらめない男、三井寿だ!