51Nod-1562-玻璃切割

来源:互联网 发布:java jdbc mysql 编辑:程序博客网 时间:2024/05/01 19:47

首先推荐这位大大的博客,我是看他的博客看懂的:
http://blog.csdn.net/f_zyj/article/details/68939756

问题描述:

现在有一块玻璃,是长方形的(w 毫米× h 毫米),现在要对他进行切割。

切割的方向有两种,横向和纵向。每一次切割之后就会有若干块玻璃被分成两块更小的玻璃。在切割之后玻璃不会被移动。

现在想知道每次切割之后面积最大的一块玻璃是多少。

样例解释:

对于第四次切割,下面四块玻璃的面积是一样大的。都是2。

Input

单组测试数据。
第一行有三个整数 w,h,n (2≤w,h≤200000, 1≤n≤200000),表示玻璃在横向上长w 毫米,纵向上长h 毫米,接下来有n次的切割。
接下来有n行输入,每一行描述一次切割。
输入的格式是H y 或 V x。
H y表示横向切割,切割线距离下边缘y毫米(1≤y≤h-1)。
V x表示纵向切割,切割线距离左边缘x毫米(1≤x≤w-1)。
输入保证不会有两次切割是一样的。

Output

对于每一次切割,输出所有玻璃中面积最大的是多少。

Input示例

样例输入1
4 3 4
H 2
V 2
V 3
V 1

Output示例

样例输出1
8
4
4
2

挺神奇的一道题,开始是用链表总,超时,然后看评论说用IO挂,多交几次有一定几率过(看人品··)。。。
这里写图片描述
然后看到网上第二种思路,用并查集来做,首先如何用并查集来表示一个区间,将点i和i+1合并,并且将他们的权值也合并,如果在某点进行了分割,就不将该点进行合并操作,然后先把每个切割线记录下来,做一次处理,得到的并查集就是对N次切割完得到的情况,接着倒着来,把每次切割的点j,与j+1进行合并操作,并合并他们的权值,同时更新最大的宽和高,再把答案存起来,最后输出。

#include<bits/stdc++.h>using namespace std;const long long maxn=2e5+10;long long mx[2];long long par[2][maxn];long long rankpar[2][maxn];long long vis[2][maxn];vector<pair<char,long long> >input;long long w,h,n;long long find(long long k,long long z){    return par[z][k]=(par[z][k]==k?k:find(par[z][k],z));}void join(long long x,long long y,long long z){    long long xx=find(x,z);    long long yy=find(y,z);    par[z][xx]=yy;    rankpar[z][yy]+=rankpar[z][xx];    mx[z]=max(mx[z],rankpar[z][yy]);}void init(){    for(long long i=0;i<2;i++)    {        for(long long j=0;j<maxn;j++)        {            par[i][j]=j;            rankpar[i][j]=1;        }    }}int main(){    cin>>w>>h>>n;    memset(vis,0,sizeof(vis));    pair<char,long long> p;    mx[0]=mx[1]=1;    init();    for(long long i=0;i<n;i++)    {        getchar();        p.first=getchar();        scanf("%d",&p.second);        input.push_back(p);        if(p.first=='H')         vis[0][p.second]=1;        else         vis[1][p.second]=1;    }    for(long long i=1;i<h;i++)    {        if(!vis[0][i])            join(i,i+1,0);    }    for(long long i=1;i<w;i++)    {        if(!vis[1][i])            join(i,i+1,1);    }    stack<long long> ans;    ans.push(mx[0]*mx[1]);    for(long long i=n-1;i>=0;i--)    {        if(input[i].first=='H')            join(input[i].second,input[i].second+1,0);        else            join(input[i].second,input[i].second+1,1);        ans.push(mx[0]*mx[1]);    }    ans.pop();    while(!ans.empty())    {        cout<<ans.top()<<endl;        ans.pop();    }}
0 0
原创粉丝点击