广工oj 1231 && 51nod 1821 加强版 思维+并查集 OR 栈
2017-08-18 12:41
357 查看
题目链接
这个应该是最基础的一道题目了.假设当时我们可以凑出(0,n)的所有数,那么只有当来的数x满足
n+1 >= x 才能保证凑出新的(0,n+x)的所有的数.否则若x为n+2 那么就无法凑出n+1 等等.
所以这个题目直接排个序,然后扫一遍 直到 ans+1 <x 停止
51nod 1821
这个题目是个加强版.要使优美值最大,那么首先将集合a,先按照上述的过程找到最大值,即直到ans + 1 <x.那么我
们在从b集合中找到满足ans + 1>=x 的最大的.这样才能使新得到的ans尽可能的大从而加入更多的x 达到最大优美值.
那么问题就转化为怎么快速的在b中找到满足条件的最大的.因为每次从b开头扫会T的.
这里肯定将所有的集合先进行了升序排序。
这里采用两个方法:
1.栈:
找到再a中的最优解后,每次将b集合中所有满足条件的解加入答案,然后每次取栈顶就是满足条件的最大的.
2.并查集
巧妙的利用并查集来维护区间.在b中找到满足条件的最后一个,如果当前他已经被使用了,那么他指向的就是它前面
第一个未被使用的,以此来实现区间的跳跃.这样每次使用完一个就把他指向前面第一个未用的,直到指向0就代表找不到
满足 ans + 1 >= x 的最优解更大的了。
这个题目的话感觉栈更好理解,并查集的应用在实现区间跨越方面也很常见.
并查集:
栈:
这个应该是最基础的一道题目了.假设当时我们可以凑出(0,n)的所有数,那么只有当来的数x满足
n+1 >= x 才能保证凑出新的(0,n+x)的所有的数.否则若x为n+2 那么就无法凑出n+1 等等.
所以这个题目直接排个序,然后扫一遍 直到 ans+1 <x 停止
int a ; int main(){ int _,n; scanf("%d",&_); while(_--){ scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d",&a[i]); } sort(a+1,a+n+1); LL ans = 0; for(int i=1;i<=n;i++){ if(ans+1>=a[i]) ans+=a[i]; else break; } printf("%lld\n",ans); } return 0; }
51nod 1821
这个题目是个加强版.要使优美值最大,那么首先将集合a,先按照上述的过程找到最大值,即直到ans + 1 <x.那么我
们在从b集合中找到满足ans + 1>=x 的最大的.这样才能使新得到的ans尽可能的大从而加入更多的x 达到最大优美值.
那么问题就转化为怎么快速的在b中找到满足条件的最大的.因为每次从b开头扫会T的.
这里肯定将所有的集合先进行了升序排序。
这里采用两个方法:
1.栈:
找到再a中的最优解后,每次将b集合中所有满足条件的解加入答案,然后每次取栈顶就是满足条件的最大的.
2.并查集
巧妙的利用并查集来维护区间.在b中找到满足条件的最后一个,如果当前他已经被使用了,那么他指向的就是它前面
第一个未被使用的,以此来实现区间的跳跃.这样每次使用完一个就把他指向前面第一个未用的,直到指向0就代表找不到
满足 ans + 1 >= x 的最优解更大的了。
这个题目的话感觉栈更好理解,并查集的应用在实现区间跨越方面也很常见.
并查集:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<stack> using namespace std; typedef long long ll; const int maxn = 1e3 + 10; int a[maxn][maxn]; int pre[maxn]; void init() { for(int i = 0;i < maxn ;i++) pre[i] = i; return ; } int find(int x) { return x == pre[x] ? x : pre[x] = find(pre[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; } int main() { int n; n = read(); for(int i = 1;i <= n;i++) { a[i][0] = read(); for(int j = 1;j <= a[i][0];j++) a[i][j] = read(); sort(a[i] + 1,a[i] + a[i][0] + 1); } int _; _ = read(); int x,y,k; while(_--) { x = read(); y = read(); k = read(); init(); int i = 1,j = 1,ans = 0; while(k--) { for(;i <= a[x][0];i++) { if(ans + 1 >= a[x][i]) ans += a[x][i]; else break; } for(; j <= a[y][0];j++) { if(a[y][j] > ans + 1) break; } j--; int f = find(j); if(!f) break; ans += a[y][f]; pre[f] = find(f-1); } for(;i <= a[x][0];i++) { if(ans + 1 >= a[x][i]) ans += a[x][i]; else break; } printf("%d\n",ans); } return 0; }
栈:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<stack> using namespace std; typedef long long ll; const int maxn = 1e3 + 10; int a[maxn][maxn]; 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; } int main() { int n; n = read(); for(int i = 1;i <= n;i++) { a[i][0] = read(); for(int j = 1;j <= a[i][0];j++) a[i][j] = read(); sort(a[i] + 1,a[i] + a[i][0] + 1); } int _; _ = read(); int x,y,k; while(_--) { x = read(); y = read(); k = read(); int i = 1,j = 1,ans = 0; stack<int>st; while(k--) { for(;i <= a[x][0];i++) { if(ans + 1 >= a[x][i]) ans += a[x][i]; else break; } for(; j <= a[y][0];j++) { if(a[y][j] <= ans + 1) st.push(a[y][j]); else break; } if(st.size()) { int num = st.top(); st.pop(); ans += num; } else break; } for(;i <= a[x][0];i++) { if(ans + 1 >= a[x][i]) ans += a[x][i]; else break; } printf("%d\n",ans); } return 0; }
相关文章推荐
- 51Nod - 1821 思维题 + 并查集 + 二分
- 51nod 1821 最优集合(贪心+并查集)
- 51nod 1535 深海探险【思维+并查集】
- 【51nod 1288 汽油补给 】 贪心 & 思维
- 51NOD 1821 最优集合 [并查集]
- 【51nod】---硬币游戏(思维&&数学)
- BZOJ3674: 可持久化并查集加强版&&BZOJ3673: 可持久化并查集 by zky
- 思维题:抽屉原理 hdu 5776 sum & 51Nod 1103 N的倍数
- bzoj3674 可持久化并查集加强版 (主席树 & 并查集)
- 51nod 1640 天气晴朗的魔法 【二分枚举最大生成树】or【最小&&最大 生成树】
- 51nod 1821 最优集合(想法+贪心+并查集)
- 51nod 1096 距离之和最小 && 1108-距离之和最小 V2(简单数学)&& 1110 距离之和最小 V3(逆思维)
- HDU3234&&UVA12232&&LA4487:Exclusive-OR(经典带权并查集)
- 【BZOJ 3674】可持久化并查集加强版&【BZOJ 3673】可持久化并查集 by zky 用可持久化线段树破之
- 【BZOJ】【3673】可持久化并查集 & 【3674】可持久化并查集加强版
- [BZOJ3674]可持久化并查集加强版&[BZOJ3673]可持久化并查集 by zky
- 并查集初学(4)向量思维 POJ1182(食物链)&& POJ1703
- 51nod 1421 最大MOD值 & codeforces 485D Maximum Value(思维 数学)
- 51nod 1163 最高的奖励 (贪心+优先队列/并查集)&& 1191 消灭兔子(贪心+优先队列维护) && 1475 建设国家 (思维枚举+优先队列)
- 51nod-1158 . 全是1的最大子矩阵 &&CODEVS-2491 玉蟾宫(枚举+单调栈 or dp)