Atlas of rruucc@POJ[PKU 1826,1827,1828]

http://162.105.81.212/JudgeOnline/problem?id=1826 

这题是以前做搜索题求最大面积的一个加强版,但是数据范围之大显然不能这样蛮搞。

题意:一个很大很大的矩形被分成n*m个格子,每份有一个坐标和一个权值,一块区域可以是很多的格子组成,求区域面积的最大权值。

分别按x排序,y排序后,然后对相邻的两个元素做如下操作:若两个坐标是相邻的则把他们放在同一个集合里。。。。。。

最后统计集合的总权值;

代码:

#include<iostream> #include<cmath> #include<algorithm> using namespace std ; const int N = 200001 ; struct Node { int x,y,v,id; }dot[N]; int n,p[N],rank[N],res[N]; int cmpx(Node a,Node b) { if(a.x!=b.x) { return a.x < b.x ; } return a.y < b.y ; } int cmpy(Node a,Node b) { if(a.y!=b.y) { return a.y < b.y ; } return a.x < b.x ; } void make_set() { for(int i=1;i<=n;i++) { p[i] = i ; rank[i] = 0 ; } } int find(int x) { if(x!=p[x]) { p[x] = find(p[x]) ; } return p[x] ; } void Un_set(int x,int y) { int rx = find(x) , ry = find(y) ; if(rank[rx]>rank[ry]) { p[ry] = rx ; }else { p[rx] = ry ; if(rank[rx] == rank[ry]) rank[ry]++ ; } } bool Is_link(int a,int b) { if(abs(dot[a].x-dot[b].x)+abs(dot[a].y-dot[b].y)==1) return true ; return false ; } int main() { while(scanf("%d",&n)&&n) { for(int i=1;i<=n;i++) { scanf("%d%d%d",&dot[i].x,&dot[i].y,&dot[i].v); dot[i].id = i ; } make_set(); sort(dot+1,dot+n+1,cmpx); int rx,ry; for(int i=1;i<n;i++) { if(Is_link(i,i+1)) { rx = find(dot[i].id) , ry = find(dot[i+1].id) ; if(rx!=ry) { Un_set(dot[i].id,dot[i+1].id); } } } sort(dot+1,dot+n+1,cmpy); for(int i=1;i<n;i++) { if(Is_link(i,i+1)) { rx = find(dot[i].id) , ry = find(dot[i+1].id) ; if(rx!=ry) { Un_set(dot[i].id,dot[i+1].id); } } } memset(res,0,sizeof(res)); for(int i=1;i<=n;i++) { res[find(dot[i].id)] += dot[i].v ; } int ans = 0 ; for(int i=1;i<=n;i++) { if(res[i]>ans) ans = res[i] ; } printf("%d/n",ans); } return 0 ; }

http://162.105.81.212/JudgeOnline/problem?id=1827 

也是一道并查集题。

题目描述:一共有x个盒子,一个盒子有一个数,一个数只能放在一个盒子里
有n个怪兽,每个随机检起一张卡片,打开获得的数字为d[i],不能改变且不能再打开其他盒子,d[i]范围[1,m]
如果第i个怪兽获得数字d[i],他只能打开编号<=d[i]的盒子,一个盒子只能给一个怪兽,一个怪兽只能由一个盒子
jim有权利去分配,他知道第i个怪兽的能力为s[i],问题要使得所有没有获得盒子的怪兽的s[i]之和sum最小

先对mons按s值排序,若s值相等则按d从大到小排,然后并查集搞,p[i]记录的是肉某怪抽到的卡片值为i是可以用分到的treasure,如果p[i]==0表明前面的treasure已经被分完了,所以不能分给他。

代码:

#include<iostream> #include<algorithm> using namespace std ; const int N = 50001 ; struct Node { int d,s; }mons[N]; int n,m,p[N]; int cmp(Node a,Node b) { if(a.s!=b.s) { return a.s > b.s ; } return a.d > b.d ; } int find(int x) { if(x!=p[x]) { p[x] = find(p[x]) ; } return p[x] ; } void Un_set(int x,int y) { int rx = find(x) , ry = find(y) ; p[ry] = p[rx] ; } int main() { while(scanf("%d%d",&n,&m)&&(n+m)) { for(int i=1;i<=n;i++) scanf("%d",&mons[i].d) ; for(int i=1;i<=n;i++) scanf("%d",&mons[i].s) ; sort(mons+1,mons+n+1,cmp); for(int i=0;i<=m;i++) { p[i] = i ; } int sum = 0 ; for(int i=1;i<=n;i++) { int rd = find(mons[i].d); if(rd == 0) { sum += mons[i].s ; continue ; } Un_set(rd-1,mons[i].d); } printf("%d/n",sum); } return 0 ; }

http://162.105.81.212/JudgeOnline/problem?id=1828

这是这三道题里最水的一道,不过想模型的时候也比较难想。按x从小到大y从小到大拍学,然后从后面扫面;每时刻记录y的最大值;

#include<iostream> #include<algorithm> using namespace std ; const int N = 50001 ; struct Node { int x,y; }p[N]; int n; int cmp(Node a,Node b) { if(a.x!=b.x) { return a.x < b.x ; } return a.y < b.y ; } int main() { while(scanf("%d",&n) && n) { for(int i=0;i<n;i++) scanf("%d%d",&p[i].x,&p[i].y); sort(p,p+n,cmp); int ans = 1 ; int c = p[n-1].y ; for(int i=n-2;i>=0;i--) { if(c<p[i].y) { c = p[i].y ; ans ++ ; } } printf("%d/n",ans); } return 0; }


 

你可能感兴趣的:(Atlas of rruucc@POJ[PKU 1826,1827,1828])