51nod 1821 最優集合(想法+貪心+並查集)
阿新 • • 發佈:2018-12-24
基準時間限制:1 秒 空間限制:131072 KB 分值: 40 難度:4級演算法題
收藏
關注
一個集合S的優美值定義為:最大的x,滿足對於任意i∈[1,x],都存在一個S的子集S',使得S'中元素之和為i。
給定n個集合,對於每一次詢問,指定一個集合S1和一個集合S2,以及一個數k,要求選擇一個S2的子集S3(|S3|<=k),使得S1∪S3的優美值最大。
(集合元素可以重複)
Input
Output
第一行一個數n,(n<=1000) 接下來n行,每行描述一個集合: 第一個數m,表示集合大小,接下來m個數,表示集合中的元素(m<=1000,元素<=10^9) 第n+2行一個數T,表示詢問次數(T<=10000) 接下來T行,每行3個數a,b,k,表示指定第a個集合為S1,第b個集合為S2,k的意義如題(a<=n,b<=n,k<=100,000)
T行,每行一個數,表示對應詢問所能達到的最大優美值Input示例
2 6 1 2 3 8 15 32 6 1 1 1 1 1 1 1 1 2 3Output示例
64﹡ LH (題目提供者)
題解:
這一題基於一個事實,加入目前集合優美值為now,那麼加入一個x(x<=now+1),可以使得集合的優美值變成x+now,那麼,我們可以先將每個集合排序,首先在第一個集合裡掃,直到此時的值大於now+1,那麼現在可以在第二個集合裡面取小於等於now+1的一個最大值,如果沒次都從頭在集合b裡面找會浪費時間,可以用一個並查集,對於b的第i個元素,假如這個元素沒有被用,那麼指向自己,否則指向find(i-1).
此外,這個題不用輸入掛是過不了的。。。有毒。。。
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<vector> #include<queue> #include<stack> using namespace std; #define rep(i,a,n) for (int i=a;i<n;i++) #define per(i,a,n) for (int i=n-1;i>=a;i--) #define pb push_back #define fi first #define se second typedef vector<int> VI; typedef long long ll; typedef pair<int,int> PII; const int inf=0x3fffffff; const ll mod=1000000007; const int maxn=1000+10; int a[maxn][maxn]; int pa[maxn]; void init() { rep(i,0,maxn) pa[i]=i; } int find(int x) { return pa[x]==x? x:pa[x]=find(pa[x]); } inline int read() { char c=getchar();int x=0,f=1; while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();} return x*f; } void solve(int p,int q,int k) { int now=0; int i=1,j=1; while(1) { if(i<=a[p][0]&&a[p][i]<=now+1) now+=a[p][i],i++; else if(k) { k--; while(j<=a[q][0]&&a[q][j]<=now+1) j++; j--; int x=find(j); if(!x) break; if(x==j) { now+=a[q][j]; pa[j]=find(j-1); j++; } else { if(!x) break; else { now+=a[q][x]; pa[x]=find(x-1); } } } else break; } printf("%d\n",now); } int main() { int n; scanf("%d",&n); rep(i,1,n+1) { a[i][0]=read(); rep(j,1,a[i][0]+1) a[i][j]=read(); sort(a[i]+1,a[i]+a[i][0]+1); } int q; scanf("%d",&q); while(q--) { int i,j,k; i=read(),j=read(),k=read(); init(); solve(i,j,k); } return 0; }