4 条题解
-
0lajioj LV 7 @ 2018-08-12 18:28:03
考虑一种新方法:括号匹配。
对于每一个圆,记录其左右分别能到达的最远点l , r。
显然 l = O(圆心) - R(半径); r = O + R。分别为左括弧和右括弧
然后得到一个2n的数组。
对于任意一个圆,其贡献仅有可能为两种:1或2,其中1不必解释,当一个圆被其他圆沿半径方向分为两半,其贡献则为2。
则考虑括弧匹配,对于任意一个左括弧,记录其贡献值add。有以下情况:- 对于连续两个'(',他们的坐标相同,则前面一个的贡献暂时为1。
- 对于')'的出现,在栈中弹出第一个元素并把他的贡献+1记录到答案
- 对于连续的两个')'的出现,且坐标相同,则栈顶的'('贡献暂时为1。
- 对于连续的')'和'('出现,若坐标相同,则栈顶的'('贡献暂时为1。
非以上情况所述,add均为0。
最后答案+1,表示最外面的区域。复杂度O(2n)#include<cstdio> #include<algorithm> #define inf 0x3f3f3f3f using namespace std; int n; const int MAXN = 300005; struct point{ int l,r,val,add; }p[MAXN<<1];point s[MAXN<<1];point p1,p2; inline bool cmp(const point a,const point b){ if(a.val == b.val) return a.r > b.r; else return a.val < b.val; } inline void read(int&x){ x = 0; bool flag = false; char c = getchar(); while (c<'0'||c>'9'){ if (c == '-') flag = true; c = getchar(); } while (c>='0'&&c<='9'){ x = x*10+c-'0'; c = getchar(); } if (flag) x = -x; } int main(){ read(n);int u = 0; for(int i=1;i<=n;++i){ int o,r;read(o);read(r); p1.val = o + r;p2.val = o - r; p1.r = 1;p1.l = 0;p2.r = 0;p2.l = 1; p1.add = p2.add = 0; p[++u] = p1; p[++u] = p2; } sort(p+1,p+1+u,cmp);int tot=0; s[++tot] = p[1];int ans = 0; int last = inf; for(int i=2;i<=u;++i){ if(p[i].l){ if(p[i].val == s[tot].val) s[tot].add = 1; if(last != inf){ if(p[i].val != last) s[tot].add = 0; } last = inf; s[++tot] = p[i]; } if(p[i].r){ if(last == inf) last = p[i].val; else{ if(p[i].val != last) s[tot].add = 0; last = p[i].val; } ans += (1 + s[tot].add); tot--; } } printf("%d",ans+1); return 0; }
-
02014-10-06 11:36:45@
既然有人把我的程序发了出来那我就说一下我的做法
先把圆转化为线段
找出每个圆的第一个祖先
意思就是 完全包含而又最小的圆
然后按左端点递增,左端点相同则右端点越远越优先排序
每个圆本来只能增加1个平面
会出现更多 是因为一些圆首尾相接把一个大圆割成了两部分
那我们只要找出每个圆的一级祖先就可以判断了
然后求每个圆的一级祖先可以用我在程序中的dfs来求出,正确性应该显然。
神犇们是否还有更好的做法,求指教? -
02014-10-06 11:35:24@
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<iostream>
#include<vector>
#include<set>
#include<map>
#include<string>
#include<algorithm>
#include<queue>
#include<list>
#define FOR(i,a,b) for(i=(a);i<=(b);i++)
#define ROF(i,a,b) for(i=(a);i>=(b);i--)
#define mmt(a,b) memset(a,b,sizeof(a))
#define pb push_back
#define mp make_pair
#define y1 fuck
#define N 700010
using namespace std;
typedef long long LL;
typedef long double LD;
struct node{int X,Y;}a[N];
int x[N],r[N],n;
bool cmp(node a,node b)
{
return a.X<b.X||(a.X==b.X&&a.Y>b.Y);
}
int divide(int x,int y)
{
if (x>=y) return 1;
int i=x+1,j=x+1,res=0,k;
while (i<=y)
{
while (j<y&&a[j+1].Y<=a[i].Y) j++;
res+=divide(i,j);
i=j+1;j++;
}
int Max=a[x].X;
FOR(k,x+1,y)
if (a[k].X<=Max) Max=max(Max,a[k].Y);
if (Max==a[x].Y) res+=2;else res+=1;
return res;
}
int main()
{
scanf("%d",&n);int i;
FOR(i,1,n)
{
scanf("%d%d",&x[i],&r[i]);
a[i].X=x[i]-r[i];a[i].Y=x[i]+r[i];
}
sort(a+1,a+1+n,cmp);
int j=1,ans=1;i=1;
while (i<=n)
{
while (j<n&&a[j+1].Y<=a[i].Y) j++;
ans+=divide(i,j);
i=j+1;j++;
}
printf("%d\n",ans);
return 0;
}
直接模拟即可 -
02014-10-06 11:23:16@
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define L 300010
using namespace std;
struct circle
{
int lp,rp,IO,father;
}po[L];
int n,ans,O,R,nows;
bool cmp(circle a,circle b)
{
if(a.lp==b.lp)
return a.rp>b.rp;
return a.lp<b.lp;
}
void dfs(int looks)
{
while(nows<=n&&po[nows].rp<=po[looks].rp)
{
po[nows].father=looks;
nows++;
dfs(nows-1);
}
return;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d%d",&O,&R);
po[i].lp=O-R;
po[i].rp=O+R;
}
sort(po+1,po+n+1,cmp);
nows=1;
po[0].rp=2147483647;
dfs(0);
for(int i=1;i<=n;i++)
po[po[i].father].IO+=(po[i].rp-po[i].lp);
ans=n+1;
for(int i=1;i<=n;i++)
if(po[i].IO==po[i].rp-po[i].lp)
ans++;
printf("%d\n",ans);
return 0;
}-------------以上dfs算法来自赵鋆峰,orz orz--------------------------------
- 1
信息
- ID
- 1883
- 难度
- 7
- 分类
- (无)
- 标签
- (无)
- 递交数
- 844
- 已通过
- 134
- 通过率
- 16%
- 被复制
- 3
- 上传者