[BJOI2016]水晶 做题心得

这是一个写了我两小时的傻逼题。写这个题浪费了一堆时间后,我才意识到我码力又不行了。于是整理起了实现技巧,开始练码力。

思路

不难。首先把 \((x,y,z)\) 变成 \((x-z,y-z)\)。因为发现 \((x,y,z)\) 同时减去某个数表示的位置不变,同时减去 \(z\),把坐标只用 \(x,y\) 来描述。

发现是关于点权的,先把每个点拆成入点和出点,连一条边表示它的点权。假设入,出点分别是 \(a_i,a_o\)

然后枚举一下每个三角形,每个直线,假设是 \((a,b,c)\)。

那么这样连边:

\(S \xrightarrow[INF]{} a_i \xrightarrow[val_a]{} a_o \xrightarrow[INF]{} b_i\xrightarrow[val_b]{} b_o\xrightarrow[INF]{} c_i\xrightarrow[val_c]{}c_o\xrightarrow[INF]{} T\)

实现问题&改进

  1. 发现这样连边会连出环来。解法是,考虑按 \((x+y)\%3\) 分类,强行钦定某个顺序。这样就不会产生环了。

  2. 分开考虑三角形和直线太麻烦了,而且非常容易写错。我因此写错了 \(114514\) 次。事实上可以一块考虑,对于每个\((x+y)\%3=0\) 的,考虑它的“六周” (“四周”这个词在本题中的引申,注意到相邻的有六个点),不能有相邻的 \(\%3=1\) 和 \(\%3=2\) 的。

    然后可以这样建,\(\%3=1\) 的接 \(S\),\(\%3=2\) 的接 \(T\),\(\%3=0\) 的,向周围的 \(\%3=2\) 的连一条,然后周围 \(\%3=1\) 的向它来连一条,就可以完成建图了

    这样结构更加清楚,简单,不容易写挂

    (是参考了一篇题解中的实现

代码

#include <bits/stdc++.h>
using namespace std;
namespace Flandre_Scarlet
{
#define N 400005
#define INF 600000000
#define F(i,l,r) for(int i=l;i<=r;++i)
#define D(i,r,l) for(int i=r;i>=l;--i)
#define Fs(i,l,r,c) for(int i=l;i<=r;c)
#define Ds(i,r,l,c) for(int i=r;i>=l;c)
#define MEM(x,a) memset(x,a,sizeof(x))
#define Tra(i,u) for(int i=G.st(u),v=G.to(i);~i;i=G.nx(i),v=G.to(i))
#define p_b push_back
#define sz(a) ((int)a.size())
#define all(a) a.begin(),a.end()
#define iter(a,p) (a.begin()+p)
int I() {char c=getchar(); int x=0; int f=1; while(c<'0' or c>'9') f=(c=='-')?-1:1,c=getchar(); while(c>='0' and c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar(); return ((f==1)?x:-x);}
template <typename T> void Rd(T& arg){arg=I();}
template <typename T,typename...Types> void Rd(T& arg,Types&...args){arg=I(); Rd(args...);}
void RA(int *p,int n) {F(i,1,n) *p=I(),++p;}
int n;
int x[N],y[N],c[N];
map<pair<int,int>,int> rec,rid;
#define rc(x,y) rec[make_pair(x,y)]
#define ri(x,y) rid[make_pair(x,y)]
void Input()
{
n=I();
F(i,1,n)
{
int z; Rd(x[i],y[i],z,c[i]); c[i]*=10;
x[i]-=z; y[i]-=z;
if ((x[i]+y[i])%3==0) c[i]+=c[i]/10; rc(x[i],y[i])+=c[i];
}
}
class NetworkFlow
{
public:
int S,T,n;
struct edge
{
int v,c,nx;
}pool_e[4000000+2]; edge *e;
int pool_h[N+2]; int *head;
int pool_c[N+2]; int *cur;
int ecnt=-1;
void clear()
{
ecnt=-1;
MEM(pool_e,-1); e=pool_e+2;
MEM(pool_h,-1); head=pool_h+2;
MEM(pool_c,-1); cur=pool_c+2;
// 允许 [-1]的访问
}
void add(int u,int v,int c)
{
e[++ecnt]={v,c,head[u]}; head[u]=ecnt;
}
void addflow(int u,int v,int c)
{
// printf("flow %d %d %d\n",u,v,c);
add(u,v,c);
add(v,u,0);
}
int& st(int u) {return head[u];}
int& cu(int u) {return cur[u];}
int& to(int i) {return e[i].v;}
int& cap(int i) {return e[i].c;}
int& nx(int i) {return e[i].nx;}
#define Trah(i,u) for(int i=st(u),v=to(i);~i;i=nx(i),v=to(i))
#define Trac(i,u) for(int &i=cu(u),v=to(i);~i;i=nx(i),v=to(i)) queue<int> Q;
int dep[N];
bool BFS()
{
while(!Q.empty()) Q.pop(); F(i,1,n) dep[i]=INF;
dep[S]=1; cur[S]=head[S]; Q.push(S);
while(!Q.empty())
{
int u=Q.front(); Q.pop();
if (u==T) return true;
Trah(i,u) if (cap(i) and dep[v]==INF)
{
dep[v]=dep[u]+1;
cur[v]=head[v];
Q.push(v);
}
}
return false;
}
int DFS(int u,int flow)
{
if (u==T) return flow;
int ans=0;
Trac(i,u)
{
if (!flow) break;
if (cap(i) and dep[v]==dep[u]+1)
{
int f=DFS(v,min(flow,cap(i)));
if (!f)
{
dep[v]=INF;
}
else
{
cap(i)-=f; cap(i^1)+=f;
flow-=f; ans+=f;
}
}
}
return ans;
}
int Dinic()
{
int ans=0;
while(BFS()) ans+=DFS(S,INF);
return ans;
} NetworkFlow() {clear();}
NetworkFlow(int s,int t,int nn) {clear(); S=s; T=t; n=nn;}
}Nt;
int tot=0,S=1,T=2;
int in[N],out[N];
void Sakuya()
{
int point=0;
tot=2;
F(i,1,n) c[i]=x[i]=y[i]=0;
for(auto p:rec)
{
int i=p.first.first,j=p.first.second;
++point; x[point]=i;
y[point]=j;
c[point]=rc(i,j);
ri(i,j)=point;
in[point]=++tot;
out[point]=++tot;
}
Nt=NetworkFlow(S,T,tot);
F(i,1,point)
{
int t=((x[i]+y[i])%3+3)%3;
if (t==1) Nt.addflow(S,in[i],INF);
if (t==2) Nt.addflow(out[i],T,INF);
else
{
int nx;
nx=ri(x[i]-1,y[i]-1); if (nx) Nt.addflow(out[nx],in[i],INF);
nx=ri(x[i]+1,y[i]); if (nx) Nt.addflow(out[nx],in[i],INF);
nx=ri(x[i],y[i]+1); if (nx) Nt.addflow(out[nx],in[i],INF); nx=ri(x[i]+1,y[i]+1); if (nx) Nt.addflow(out[i],in[nx],INF);
nx=ri(x[i]-1,y[i]); if (nx) Nt.addflow(out[i],in[nx],INF);
nx=ri(x[i],y[i]-1); if (nx) Nt.addflow(out[i],in[nx],INF);
}
Nt.addflow(in[i],out[i],c[i]);
} int sum=0; F(i,1,point) sum+=c[i];
int ans=sum-Nt.Dinic();
printf("%d.%d\n",ans/10,ans%10);
}
void IsMyWife()
{
Input();
Sakuya();
}
}
#undef int //long long
int main()
{
Flandre_Scarlet::IsMyWife();
getchar();
return 0;
}

后记:两种实现的比较

  1. 原实现长达 \(220\) 行,改进实现只有 \(182\) 行。

  2. 原实现(提到过)WA了 \(114514\) 次,最高拿了 \(35\),到现在还不知道问题在哪,没调出来,也不想调了,nmsl (暴躁)

    相比较改进实现一遍就A了。

所以说,码力的提升还是很重要的。

[BJOI2016]水晶 做题心得的更多相关文章

  1. [JSOI2019]节日庆典 做题心得

    [JSOI2019]节日庆典 做题心得 一个性质有趣的字符串题 这要是在考场上我肯定做不出来吧 一开始还以为要 SAM 什么的暴力搞,没想到只用到了 \(Z\) 函数 -- 也是我生疏了罢 (学了啥忘 ...

  2. CF1416D 做题心得

    CF1416D 做题心得 上次在某trick中提到了这个题,一开始觉得太毒瘤没有写,现在把它补上了. 感觉实现这个东西,比单纯收获一个trick,收获的东西多太多了. 主要思路 它的主要trick是& ...

  3. [NOIP补坑计划]NOIP2017 题解&做题心得

    终于做完了…… 场上预计得分:?(省一分数线:295) 由于看过部分题解所以没有预计得分qwq 题解: D1T1 小凯的疑惑 题面 震惊!一道小学奥数题竟难倒无数高中考生! 欢迎大家以各种姿势*和谐* ...

  4. [NOIP补坑计划]NOIP2016 题解&做题心得

    感觉16年好难啊QAQ,两天的T2T3是不是都放反了啊…… 场上预计得分:100+80+100+100+65+100=545(省一分数线280) ps:loj没有部分分,部分分见洛咕 题解: D1T1 ...

  5. [NOIP补坑计划]NOIP2015 题解&做题心得

    感觉从15年开始noip就变难了?(虽然自己都做出来了……) 场上预计得分:100+100+60~100+100+100+100=560~600(省一分数线365) 题解: D1T1 神奇的幻方 题面 ...

  6. [NOIP补坑计划]NOIP2013 题解&做题心得

    场上预计得分:100+100+100+100+100+60=560(省一分数线410) 五道傻逼题+一道大搜索题…… 题解: D1T1 转圈游戏 题面 水题送温暖~ #include<algor ...

  7. [NOIP补坑计划]NOIP2012 题解&做题心得

    场上预计得分:100+90+70+100+100+3060=490520(省一分数线245) 题解: D1T1 Vigenère 密码 题面 水题送温暖~~ #include<iostream& ...

  8. [NOIP补坑计划]NOIP2014 题解&做题心得

    六道普及组题,没啥好说的 场上预计得分:100+100+100+100+100+100=600(省一分数线490) (AK是不可能AK的,这辈子不可能AK的) 题解: D1T1 生活大爆炸版石头剪刀布 ...

  9. 标 题: [心得]传统IT转互联网面试经验分享

    发信人: lgonnet (逃之夭夭), 信区: Java标  题: [心得]传统IT转互联网面试经验分享发信站: 水木社区 (Wed Jul  1 10:18:38 2015), 站内 统一回复一下 ...

随机推荐

  1. 解决使用Navicat等工具进行连接登录mysql的1521错误,(mysql为8.0版本)

    mysql 8.0的版本的加密方式和以前的不一样,因此使用Navicat等工具进行连接的时候,会报1521的异常. 解决方法如下: 登录mysql的命令行工具,输入如下代码: ALTER USER ' ...

  2. TurtleBot3 Waffle (tx2版华夫)(3)opencr系统安装

    3. 1. 安装 Arduino IDE Opencr的安装环境的安装包,双击打开即可.进入安装的过程. 在这里你可以选择自己的安装位置. 安装已经完成,点击CLOSE 即可. 3.2. opencr ...

  3. CVE-2021-3019 漏洞细节纰漏

    CVE编号 CVE-2021-3019 lanproxy任意文件读取 该漏洞是2021年比较新的漏洞 是否需要认证:否 是否执行远程代码:否 是否执行远程命令:否 数据读取是否内网:否 漏洞软件介绍 ...

  4. Adnc如何本地调试 - 一个轻量级的.Net Core微服务开发框架

    前言     Adnc是一个轻量级的.Net Core微服务开发框架,同样适用于单体架构系统的开发.     如果只是想本地调试,只需要安装必备软件,必备软件除开发工具外,其它软件建议大家都使用`do ...

  5. Beta冲刺——第十天(补发)

    这个作业属于哪个课程 https://edu.cnblogs.com/campus/fzzcxy/2018SE1 这个作业要求在哪里 https://edu.cnblogs.com/campus/fz ...

  6. Redis学习之路(四)Redis-cluster java api操作

    import redis.clients.jedis.HostAndPort;import redis.clients.jedis.JedisCluster;import java.util.Hash ...

  7. 阿里云centos7安装mysql8数据库

    一.安装mysql 1. mysql官网查找仓库源镜像,选择downloads https://www.mysql.com/downloads/ 2. 找到社区版 3. 选择yum仓库 4. 选择对应 ...

  8. 我的开源项目在五个月内超过了 600 star

    其实我在 2016 年年底就开始写了这个项目:Forest,一个能够将 HTTP 的所有请求信息(包括 URL .Header 以及 Body 等信息)绑定到您自定义的 Interface 方法上,能 ...

  9. 2018年第九届蓝桥杯B组(201806-----递增三元组)

    给定三个整数数组 A = [A1, A2, - AN], B = [B1, B2, - BN], C = [C1, C2, - CN], 请你统计有多少个三元组(i, j, k) 满足: 1 < ...

  10. MyBatis中id回填的两种方式

    在一种场景下需要刚刚插入数据的ID,如果数据少可以先看数据库,记下ID,但数据很多,假设一万个用户并发,每个用户都插入自己的ID,就很难记下来. 下面给定一个场景: 1 User user = new ...