1821 最优集合(单调栈+模拟)

1821 最优集合

基准时间限制: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

第一行一个数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)

Output

T行,每行一个数,表示对应询问所能达到的最大优美值

Input示例

2

6 1 2 3 8 15 32

6 1 1 1 1 1 1

1

1 2 3

Output示例

64

 

//题解:先思考如何求出两个集合的优美值,如果 A 集合部分元素可以优美值为 x ,那么,如果 A 中有一个数是 y <= x+1 ,那么,优美值可以变为 x+y 。两个集合可以互补,如果将两个集合排好序,当仅靠 A 的元素优美值为 p 不能上升后,从 B 中选一个 <= p+1 的最大数补充,然后再考虑 A 集合的元素再扩大 p 。。。以此模拟即可,用单调栈优化 B 集合,每次查询约 2*m ,还有就是又是卡读入的题

 

  1 # include <cstdio>
  2 # include <cstring>
  3 # include <cstdlib>
  4 # include <iostream>
  5 # include <vector>
  6 # include <queue>
  7 # include <stack>
  8 # include <map>
  9 # include <bitset>
 10 # include <sstream>
 11 # include <set>
 12 # include <cmath>
 13 # include <algorithm>
 14 # pragma  comment(linker,"/STACK:102400000,102400000")
 15 using namespace std;
 16 # define LL          long long
 17 # define pr          pair
 18 # define mkp         make_pair
 19 # define lowbit(x)   ((x)&(-x))
 20 # define PI          acos(-1.0)
 21 # define INF         0x3f3f3f3f3f3f3f3f
 22 # define eps         1e-8
 23 # define MOD         1000000007
 24 
 25 namespace fastIO{
 26     #define BUF_SIZE 100000
 27     #define OUT_SIZE 100000
 28     #define ll long long
 29     //fread->read
 30     bool IOerror=0;
 31     inline char nc(){
 32         static char buf[BUF_SIZE],*p1=buf+BUF_SIZE,*pend=buf+BUF_SIZE;
 33         if (p1==pend){
 34             p1=buf; pend=buf+fread(buf,1,BUF_SIZE,stdin);
 35             if (pend==p1){IOerror=1;return -1;}
 36             //{printf("IO error!\n");system("pause");for (;;);exit(0);}
 37         }
 38         return *p1++;
 39     }
 40     inline bool blank(char ch){return ch==' '||ch=='\n'||ch=='\r'||ch=='\t';}
 41     inline void read(int &x){
 42         bool sign=0; char ch=nc(); x=0;
 43         for (;blank(ch);ch=nc());
 44         if (IOerror)return;
 45         if (ch=='-')sign=1,ch=nc();
 46         for (;ch>='0'&&ch<='9';ch=nc())x=x*10+ch-'0';
 47         if (sign)x=-x;
 48     }
 49     inline void read(ll &x){
 50         bool sign=0; char ch=nc(); x=0;
 51         for (;blank(ch);ch=nc());
 52         if (IOerror)return;
 53         if (ch=='-')sign=1,ch=nc();
 54         for (;ch>='0'&&ch<='9';ch=nc())x=x*10+ch-'0';
 55         if (sign)x=-x;
 56     }
 57     inline void read(double &x){
 58         bool sign=0; char ch=nc(); x=0;
 59         for (;blank(ch);ch=nc());
 60         if (IOerror)return;
 61         if (ch=='-')sign=1,ch=nc();
 62         for (;ch>='0'&&ch<='9';ch=nc())x=x*10+ch-'0';
 63         if (ch=='.'){
 64             double tmp=1; ch=nc();
 65             for (;ch>='0'&&ch<='9';ch=nc())tmp/=10.0,x+=tmp*(ch-'0');
 66         }
 67         if (sign)x=-x;
 68     }
 69     inline void read(char *s){
 70         char ch=nc();
 71         for (;blank(ch);ch=nc());
 72         if (IOerror)return;
 73         for (;!blank(ch)&&!IOerror;ch=nc())*s++=ch;
 74         *s=0;
 75     }
 76     inline void read(char &c){
 77         for (c=nc();blank(c);c=nc());
 78         if (IOerror){c=-1;return;}
 79     }
 80     //getchar->read
 81     inline void read1(int &x){
 82         char ch;int bo=0;x=0;
 83         for (ch=getchar();ch<'0'||ch>'9';ch=getchar())if (ch=='-')bo=1;
 84         for (;ch>='0'&&ch<='9';x=x*10+ch-'0',ch=getchar());
 85         if (bo)x=-x;
 86     }
 87     inline void read1(ll &x){
 88         char ch;int bo=0;x=0;
 89         for (ch=getchar();ch<'0'||ch>'9';ch=getchar())if (ch=='-')bo=1;
 90         for (;ch>='0'&&ch<='9';x=x*10+ch-'0',ch=getchar());
 91         if (bo)x=-x;
 92     }
 93     inline void read1(double &x){
 94         char ch;int bo=0;x=0;
 95         for (ch=getchar();ch<'0'||ch>'9';ch=getchar())if (ch=='-')bo=1;
 96         for (;ch>='0'&&ch<='9';x=x*10+ch-'0',ch=getchar());
 97         if (ch=='.'){
 98             double tmp=1;
 99             for (ch=getchar();ch>='0'&&ch<='9';tmp/=10.0,x+=tmp*(ch-'0'),ch=getchar());
100         }
101         if (bo)x=-x;
102     }
103     inline void read1(char *s){
104         char ch=getchar();
105         for (;blank(ch);ch=getchar());
106         for (;!blank(ch);ch=getchar())*s++=ch;
107         *s=0;
108     }
109     inline void read1(char &c){for (c=getchar();blank(c);c=getchar());}
110     //scanf->read
111     inline void read2(int &x){scanf("%d",&x);}
112     inline void read2(ll &x){
113         #ifdef _WIN32
114             scanf("%I64d",&x);
115         #else
116         #ifdef __linux
117             scanf("%lld",&x);
118         #else
119             puts("error:can't recognize the system!");
120         #endif
121         #endif
122     }
123     inline void read2(double &x){scanf("%lf",&x);}
124     inline void read2(char *s){scanf("%s",s);}
125     inline void read2(char &c){scanf(" %c",&c);}
126     inline void readln2(char *s){gets(s);}
127     //fwrite->write
128     struct Ostream_fwrite{
129         char *buf,*p1,*pend;
130         Ostream_fwrite(){buf=new char[BUF_SIZE];p1=buf;pend=buf+BUF_SIZE;}
131         void out(char ch){
132             if (p1==pend){
133                 fwrite(buf,1,BUF_SIZE,stdout);p1=buf;
134             }
135             *p1++=ch;
136         }
137         void print(int x){
138             static char s[15],*s1;s1=s;
139             if (!x)*s1++='0';if (x<0)out('-'),x=-x;
140             while(x)*s1++=x%10+'0',x/=10;
141             while(s1--!=s)out(*s1);
142         }
143         void println(int x){
144             static char s[15],*s1;s1=s;
145             if (!x)*s1++='0';if (x<0)out('-'),x=-x;
146             while(x)*s1++=x%10+'0',x/=10;
147             while(s1--!=s)out(*s1); out('\n');
148         }
149         void print(ll x){
150             static char s[25],*s1;s1=s;
151             if (!x)*s1++='0';if (x<0)out('-'),x=-x;
152             while(x)*s1++=x%10+'0',x/=10;
153             while(s1--!=s)out(*s1);
154         }
155         void println(ll x){
156             static char s[25],*s1;s1=s;
157             if (!x)*s1++='0';if (x<0)out('-'),x=-x;
158             while(x)*s1++=x%10+'0',x/=10;
159             while(s1--!=s)out(*s1); out('\n');
160         }
161         void print(double x,int y){
162             static ll mul[]={1,10,100,1000,10000,100000,1000000,10000000,100000000,
163                 1000000000,10000000000LL,100000000000LL,1000000000000LL,10000000000000LL,
164                 100000000000000LL,1000000000000000LL,10000000000000000LL,100000000000000000LL};
165             if (x<-1e-12)out('-'),x=-x;x*=mul[y];
166             ll x1=(ll)floor(x); if (x-floor(x)>=0.5)++x1;
167             ll x2=x1/mul[y],x3=x1-x2*mul[y]; print(x2);
168             if (y>0){out('.'); for (size_t i=1;i<y&&x3*mul[i]<mul[y];out('0'),++i); print(x3);}
169         }
170         void println(double x,int y){print(x,y);out('\n');}
171         void print(char *s){while (*s)out(*s++);}
172         void println(char *s){while (*s)out(*s++);out('\n');}
173         void flush(){if (p1!=buf){fwrite(buf,1,p1-buf,stdout);p1=buf;}}
174         ~Ostream_fwrite(){flush();}
175     }Ostream;
176     inline void print(int x){Ostream.print(x);}
177     inline void println(int x){Ostream.println(x);}
178     inline void print(char x){Ostream.out(x);}
179     inline void println(char x){Ostream.out(x);Ostream.out('\n');}
180     inline void print(ll x){Ostream.print(x);}
181     inline void println(ll x){Ostream.println(x);}
182     inline void print(double x,int y){Ostream.print(x,y);}
183     inline void println(double x,int y){Ostream.println(x,y);}
184     inline void print(char *s){Ostream.print(s);}
185     inline void println(char *s){Ostream.println(s);}
186     inline void println(){Ostream.out('\n');}
187     inline void flush(){Ostream.flush();}
188     //puts->write
189     char Out[OUT_SIZE],*o=Out;
190     inline void print1(int x){
191         static char buf[15];
192         char *p1=buf;if (!x)*p1++='0';if (x<0)*o++='-',x=-x;
193         while(x)*p1++=x%10+'0',x/=10;
194         while(p1--!=buf)*o++=*p1;
195     }
196     inline void println1(int x){print1(x);*o++='\n';}
197     inline void print1(ll x){
198         static char buf[25];
199         char *p1=buf;if (!x)*p1++='0';if (x<0)*o++='-',x=-x;
200         while(x)*p1++=x%10+'0',x/=10;
201         while(p1--!=buf)*o++=*p1;
202     }
203     inline void println1(ll x){print1(x);*o++='\n';}
204     inline void print1(char c){*o++=c;}
205     inline void println1(char c){*o++=c;*o++='\n';}
206     inline void print1(char *s){while (*s)*o++=*s++;}
207     inline void println1(char *s){print1(s);*o++='\n';}
208     inline void println1(){*o++='\n';}
209     inline void flush1(){if (o!=Out){if (*(o-1)=='\n')*--o=0;puts(Out);}}
210     struct puts_write{
211         ~puts_write(){flush1();}
212     }_puts;
213     inline void print2(int x){printf("%d",x);}
214     inline void println2(int x){printf("%d\n",x);}
215     inline void print2(char x){printf("%c",x);}
216     inline void println2(char x){printf("%c\n",x);}
217     inline void print2(ll x){
218         #ifdef _WIN32
219             printf("%I64d",x);
220         #else
221         #ifdef __linux
222             printf("%lld",x);
223         #else
224             puts("error:can't recognize the system!");
225         #endif
226         #endif
227     }
228     inline void println2(ll x){print2(x);printf("\n");}
229     inline void println2(){printf("\n");}
230     #undef ll
231     #undef OUT_SIZE
232     #undef BUF_SIZE
233 };
234 using namespace fastIO;
235 
236 # define MX 1005
237 /**************************/
238 
239 int n;
240 vector<int> v[MX];
241 
242 LL cal(int a,int b,int k)
243 {
244     stack<int> st;
245     LL ut=0;
246     int tims=0; //b 用了几次
247     int pb=0;   //指到了b 的那个位置
248     for (int i=0;i<v[a].size();)
249     {
250         if (v[a][i]<=ut+1)
251         {
252             ut+=v[a][i];
253             i++;
254         }
255         else if (tims<k)
256         {
257             while (pb<v[b].size()&&v[b][pb]<=ut+1) st.push(v[b][pb++]);
258             tims++;
259             if (st.size())
260             {
261                 ut+=st.top();
262                 st.pop();
263             }
264             else return ut;
265         }
266         else return ut;
267     }
268     while (tims<k)
269     {
270         while (pb<v[b].size()&&v[b][pb]<=ut+1) st.push(v[b][pb++]);
271         tims++;
272         if (st.size())
273         {
274             ut+=st.top();
275             st.pop();
276         }
277         else return ut;
278     }
279     return ut;
280 }
281 
282 int main()
283 {
284     scanf("%d",&n);
285     for (int i=1;i<=n;++i)
286     {
287         int m;
288         fastIO::read(m);
289         for (int j=1;j<=m;j++)
290         {
291             int x;
292             read(x);
293             v[i].push_back(x);
294         }
295         sort(v[i].begin(),v[i].end());
296     }
297     int t;
298     fastIO::read(t);
299     while (t--)
300     {
301         int a,b,k;
302         fastIO::read(a); fastIO::read(b); fastIO::read(k);
303         fastIO::println(cal(a,b,k));
304     }
305     return 0;
306 }
View Code

 

posted @ 2017-09-04 20:19  happy_codes  阅读(246)  评论(0编辑  收藏  举报