1821 最优集合(单调栈+模拟)
一个集合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 }