Codeforces Round #418 (Div. 2) D. An overnight dance in discotheque


题意: 给\(n(n <= 1000)\)个圆,圆与圆之间不存在相交关系,只存在包含与不包含关系,现在问你把这一堆圆分成两组,求每组圆的异或并和的最大值。

思路:最简单的做法是贪心的做法,算出每个圆被包含的次数,为偶数则贡献为正,奇数为贡献为负。

现在主要学习一下树形dp的做法

由于圆不存在相交的情况,所以可以把所有的圆建成树,即把每棵树上的点分成两组,分别建成两棵树

使得ans=所有偶数深度的点\(\sum{area_i}\) - 所有奇数深度的点\(\sum{area_j}\)最大。

由于每棵树是独立的,对每棵树做树形dp就好了

然而题解的状态定义简直难想的一p,没做过类似套路的题,根本想不出嘛,还是贪心做这道题比较靠谱

不过套路还是要学的

dp[u][p1][p2] 表示假定在u的祖先中p1个点给了第一颗树,剩下p2个点给了第二棵树,以u为根的子树能获得的最大价值(题做的少,感觉这样的定义好奇特啊)

考虑u分给第一棵树 或者 第二颗树 则有如下转移方程

\(\begin{equation}
dp[u][p1][p2] = max
\begin{cases}
\sum_{v \epsilon child(u)} dp[v][p1+1][p2]+(p1\%2==0?1:-1)*area[u] \\
\sum_{v\epsilon child(u)}dp[v][p1][p2+1]+(p2\%2==0?1:-1)*area[u]
\end{cases}
\end{equation}\)

这个方程看起来似乎可以从上往下做状态转移啊,仔细一想树一旦分叉,祖先结点就被考虑多次,转移就出错了,所以只能从下到上。

注意到状态转移其实只跟奇偶有关

则可以定义成dp[u][0/1][0/1]表示假定在u的祖先中给了第一棵树的点数的奇偶,给了第二颗树的点数的奇偶,子树u能获得的最大价值。

于是可以写成这样 \(dp[u][0/1][0/1]\)

\(\begin{equation}
dp[u][i][j] = max
\begin{cases}
(\sum_{v \epsilon child(u)} dp[v][i\ xor\ 1][j])+(i==0?1:-1)*area[u] \\
(\sum_{v\epsilon child(u)}dp[v][i][j\ xor\ 1])+(j==0?1:-1)*area[u]
\end{cases}
\end{equation}\)

  • 分析一下,由于每个点贡献是它在树中的深度有关,如果我们不假定它的祖先的状态的话,那么就无法从下到上做计算的。算出子树的值转移给祖先,这样最后的答案就是dp[root][0][0] (树根没有祖先当然是0,0)
#include<bits/stdc++.h>
#include<ext/pb_ds/assoc_container.hpp>
#define LL long long
#define P pair<string,int>
#define ls(i) seg[i].lc
#define rs(i) seg[i].rc
using namespace std;
using namespace __gnu_pbds;
const int N = 1e3 + 10;
const double PI = acos(-1.0);
vector<int> G[N];
int vis[N];
long double area[N];
struct circle{
int x,y,r;
circle(){};
bool operator<(const circle &rhs)const{
if(r != rhs.r) return r < rhs.r;
if(x != rhs.x) return x < rhs.x;
return y < rhs.y;
}
}c[N];
LL sqr(int x){
return 1LL * x * x;
}
bool contain(int a,int b){
return sqr(c[a].x - c[b].x) + sqr(c[a].y - c[b].y) <= sqr(c[a].r - c[b].r);
}
double dp[N][2][2];
void dfs(int u){
double s[2][2] = {0};
for(int i = 0;i < G[u].size();i++){
int v = G[u][i];
dfs(v);
for(int j = 0;j < 2;j++)
for(int k = 0;k < 2;k++)
s[j][k] += dp[v][j][k];
}
for(int i = 0;i < 2;i++)
for(int j = 0;j < 2;j++){
dp[u][i][j] = max(s[i^1][j]+(i==0?1:-1)*area[u],s[i][j^1]+(j==0?1:-1)*area[u]);
}
}
int main()
{
int n;
cin>>n;
for(int i = 1;i <= n;i++) scanf("%d%d%d",&c[i].x,&c[i].y,&c[i].r);
sort(c+1,c+n+1);
for(int i =1 ;i <= n;i++) vis[i] = 0;
for(int i = 1;i <= n;i++){
area[i] = PI * c[i].r * c[i].r;
for(int j = 1 ;j < i;j++){
if(!vis[j] && contain(i,j)){
G[i].push_back(j);
vis[j]++;
assert(vis[j]==1);
}
}
}
double ans = 0;
for(int i = 1;i <= n;i++) if(!vis[i]){
dfs(i);
ans += dp[i][0][0];
}
printf("%.10lf\n",ans);
return 0;
}

Codeforces Round #418 (Div. 2) D. An overnight dance in discotheque的更多相关文章

  1. Codeforces Round #418 (Div. 2).C two points

    C. An impassioned circulation of affection time limit per test 2 seconds memory limit per test 256 m ...

  2. Codeforces Round #418 (Div. 2)

    A: 不细心WA了好多次 题意:给你一个a序列,再给你个b序列,你需要用b序列中的数字去替换a序列中的0,如果能够替换,则需要判断a是否能构成一个非递增的序列,a,b中所有的数字不会重复 思路:就是一 ...

  3. Codeforces Round #418 (Div. 2) B. An express train to reveries

    time limit per test 1 second memory limit per test 256 megabytes input standard input output standar ...

  4. Codeforces Round #418 (Div. 2)D

    给n个圆要么包含,要么相分离,没有两个公共点,当成一棵树,把包含的面积大的放在上面 如图最上面的par记为-1,level记为0,当par==-1||level==1时就加否则减, 就是第一,二层先加 ...

  5. Codeforces Round #418 (Div. 2) A+B+C!

    终判才知道自己失了智.本场据说是chinese专场,可是请允许我吐槽一下题意! A. An abandoned sentiment from past shabi贪心手残for循环边界写错了竟然还过了 ...

  6. Codeforces Round #418 (Div. 2) C

    Description Nadeko's birthday is approaching! As she decorated the room for the party, a long garlan ...

  7. Codeforces Round #418 (Div. 2) B

    Description Sengoku still remembers the mysterious "colourful meteoroids" she discovered w ...

  8. Codeforces Round #418 (Div. 2) A

    Description A few years ago, Hitagi encountered a giant crab, who stole the whole of her body weight ...

  9. Codeforces Round #418 (Div. 2) C. An impassioned circulation of affection

    C. An impassioned circulation of affection time limit per test 2 seconds memory limit per test 256 m ...

随机推荐

  1. web攻击技术与防护

    一.跨站脚本攻击(XSS) 跨站脚本攻击是指通过存在安全漏洞的Web网站注册用户的浏览器运行非法的HTML标签或JavaScript进行的一种攻击.动态创建的HTML部分有可能隐藏着安全漏洞.就这样, ...

  2. ZJOI2019Round#2

    乱听课记录 关于树的分治问题&杂题选讲 张哲宇 边分治 (边分不是很鸡肋吗) 例题一 题目大意:给出两颗有正负边权的树,求出两个点\(u,v​\)使得两棵树中\((u,v)​\)距离的和最大. ...

  3. Linux新建用户后的必要设置

    系统:ubnutu 18.04  x64 以下操作全在root下 准备工作: 新建用户  useradd  -m  tom 初始化密码  passwd  tom 1. tab按键 不能自动单词不全 # ...

  4. shell脚本结构化语句

    本文中记录一下shell中的两种循环语句:for和while for循环 for循环是linux shell中最常用的结构,for循环有三种结构:1.列表for循环.2.不带列表for循环.3.C风格 ...

  5. Mysql_Binary_Install_Scripts(采用二进制方式安装)

    1.1    MYSQL实现代码 #!/bin/bash ######################################## #auth:wolf_dreams #time:2018-1 ...

  6. aop设计原理

    本文摘自 博文--<Spring设计思想>AOP设计基本原理 0.前言 Spring 提供了AOP(Aspect Oriented Programming) 的支持, 那么,什么是AOP呢 ...

  7. Unexpected exception parsing XML document from ServletContext resource [/WEB-INF/config/springdemo-config.xml]

    org.springframework.beans.factory.BeanDefinitionStoreException: Unexpected exception parsing XML doc ...

  8. Windows Server 远程桌面连接不上问题解决

    关于Windows Server 远程桌面连接不上的问题需要从服务.端口.防火墙这几方面进行检查: 服务器上需要 开启的服务: - Remote Access Auto Connection Mana ...

  9. 17-比赛1 D - IPC Trainers (贪心 + 优先队列)

    题目描述 本次印度编程训练营(Indian Programming Camp,IPC)共请到了 N 名教练.训练营的日程安排有 M 天,每天最多上一节课.第 i 名教练在第 Di 天到达,直到训练营结 ...

  10. SpringMVC---四大注解

    SpringMVC四大注解 Component 通用标注,在不清楚使用哪个注解的时候,可以使用Component通用注解 Controller 标注web请求控制器 Service 标注Service ...