[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. [leetcode]404. Sum of Left Leaves左叶子之和

    弄个flag记录是不是左节点就行 int res = 0; public int sumOfLeftLeaves(TreeNode root) { if (root==null) return res ...

  2. Hadoop支持的压缩格式对比和应用场景以及Hadoop native库

    对于文件的存储.传输.磁盘IO读取等操作在使用Hadoop生态圈的存储系统时是非常常见的,而文件的大小等直接影响了这些操作的速度以及对磁盘空间的消耗. 此时,一种常用的方式就是对文件进行压缩.但文件被 ...

  3. SICP 课程总结 & 复习

    SICP 课程总结 & 复习 小作文 有赖于那个终极的.伟大的.命定的教务系统,我选上了这门课:SICP,Structure and Interpret of Computer Program ...

  4. 【排序】题解_P1093奖学金

    题目描述 奖学金 某小学最近得到了一笔赞助,打算拿出其中一部分为学习成绩优秀的前5名学生发奖学金.期末,每个学生都有3门课的成绩:语文.数学.英语.先按总分从高到低排序,如果两个同学总分相同,再按语文 ...

  5. Sql Server Sum函数的特殊使用

    利用Sql Server的Sum函数开窗得到累计值 具体详解https://www.cnblogs.com/zhaoshujie/p/9594676.html 个人示例例子 DECLARE @Sale ...

  6. Java向指定Excel写入读取数据

    今天在开发中遇到用户列表导入导出的功能实现,这里了解到使用POI函数库可以完成此任务!特此记录一下 POI Apache POI是Apache软件基金会开放的源码函数库,POI提供API给Java程序 ...

  7. Centos 6.5 Rabbitmq 安装和集群,镜像部署

    centos 6.5 rabbitmq 安装和集群,镜像部署 安装erlang: yum install gcc glibc-devel make ncurses-devel openssl-deve ...

  8. 【Linux】CentOS7中yumbackend.py进程的结束方法

    环境: CentOS Linux release 7.3.1611 (Core) 今天启动这个不怎么用的机器,才启动,就发现后台的yum无法进行安装,持续报这个错误 Loaded plugins: f ...

  9. 【Linux】linux中通过date命令获取昨天或明天时间的方法

    date +"%F" 输出格式:2011-12-31 date +"%F %H:%M:%S" 输出格式:2011-12-31 16:29:50 这都是打印出系统 ...

  10. EnvironmentPostProcessor怎么做单元测试?阿里P7解答

    简介 从Spring Boot 1.3开始,我们可以在应用程序上下文刷新之前使用EnvironmentPostProcessor来自定义应用程序的Environment.Environment表示当前 ...