您的位置:首页 > 其它

广工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 停止

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐