7.28 NOI模拟赛 H2O 笛卡尔树 并查集 贪心 长链剖分
LINK:H2O


这场比赛打的稀烂 爆蛋.
只会暴力.感觉暴力细节比较多不想写.
其实这道题的难点就在于 采取什么样的策略放海绵猫.
知道了这一点才能确定每次放完海绵猫后的答案.
暴力枚举是不行的。而我们又想不到怎么做?
此时需要考虑一维的情况 化简问题 在数轴上进行贪心.
可以发现全局最大值挡住了左右两边 也就是说左右两边是完全独立的。
继续思考 递归左边此时区间全局最大值也是如此.
一个容易观察到的是 l和r相邻 较大的那个一定在较小之后选择.
那么其实就是递归所有的地方来比较 从而进行选择.
删掉之后带来的影响 其实是一路递归下来的树的影响.
其实就是笛卡尔树了 进一步发现每个节点和父亲的边删掉都会有权值 这样是我们进行第一次删掉时的答案的体现.
从而发现第一次删掉是最长链 那么就可以长链剖分维护贪心了.
考虑二维的情况.
我们还是考虑把树建立出来进行长链剖分.
怎么建树 全局最大值肯定为根节点.
然后选出全局次大的节点进行连边 类比一下即可.
值得注意的是 正着做有联通块什么的会不断分裂。反着就可以用并查集合并.
排序之后反着做就可以把树建出来了.
笛卡尔树的建立也要学会 最近遇到的比较多了!
code
//#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<ctime>
#include<cctype>
#include<queue>
#include<deque>
#include<stack>
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cstring>
#include<string>
#include<ctime>
#include<cmath>
#include<cctype>
#include<cstdlib>
#include<queue>
#include<deque>
#include<stack>
#include<vector>
#include<algorithm>
#include<utility>
#include<bitset>
#include<set>
#include<map>
#define ll long long
#define db double
#define INF 1000000000
#define inf 100000000000000000ll
#define ldb long double
#define pb push_back
#define put_(x) printf("%d ",x);
#define get(x) x=read()
#define gt(x) scanf("%d",&x)
#define gi(x) scanf("%lf",&x)
#define put(x) printf("%d\n",x)
#define putl(x) printf("%lld\n",x)
#define rep(p,n,i) for(RE int i=p;i<=n;++i)
#define go(x) for(int i=lin[x],tn=ver[i];i;tn=ver[i=nex[i]])
#define fep(n,p,i) for(RE int i=n;i>=p;--i)
#define vep(p,n,i) for(RE int i=p;i<n;++i)
#define pii pair<int,int>
#define mk make_pair
#define RE register
#define P 1000000007ll
#define gf(x) scanf("%lf",&x)
#define pf(x) ((x)*(x))
#define uint unsigned long long
#define ui unsigned
#define EPS 1e-10
#define sq sqrt
#define S second
#define F first
#define mod 1000000007
#define id(i,j) ((i-1)*m+j)
#define max(x,y) ((x)<(y)?y:x)
using namespace std;
char *fs,*ft,buf[1<<15];
inline char gc()
{
return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;
}
inline int read()
{
RE int x=0,f=1;RE char ch=gc();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=gc();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=gc();}
return x*f;
}
const int MAXN=510,maxn=MAXN*MAXN;
int n,m,top,rt,k,len,num;
int a[maxn],f[MAXN],son[MAXN],sz[MAXN];
ll c[MAXN],mx[MAXN],ans,cnt;
int lin[maxn],ver[maxn],nex[maxn];
inline void add(int x,int y)
{
ver[++len]=y;
nex[len]=lin[x];
lin[x]=len;
}
priority_queue<ll>q;
inline int getfather(int x){return x==f[x]?x:f[x]=getfather(f[x]);}
struct wy
{
int x,y;
int z;
inline bool operator <(wy a)const{return z<a.z;}
}t[maxn];
int dx[4]={0,0,1,-1};
int dy[4]={1,-1,0,0};
inline void dfs(int x)
{
sz[x]=1;
go(x)
{
dfs(tn);
c[tn]=(ll)(a[x]-a[tn])*sz[tn];
ans+=c[tn];mx[tn]+=c[tn];
if(mx[tn]>mx[x])
{
mx[x]=mx[tn];
son[x]=tn;
}
sz[x]+=sz[tn];
}
}
inline void dp(int x,int fa)
{
if(x==fa)q.push(mx[x]);
if(son[x])dp(son[x],fa);
go(x)if(tn!=son[x])dp(tn,tn);
}
int main()
{
//freopen("1.in","r",stdin);
get(n);get(m);get(k);
rep(1,n,i)rep(1,m,j)
{
int get(x);
f[id(i,j)]=id(i,j);
t[++num]=(wy){i,j,x};
}
//cout<<id(1,2)<<endl;
sort(t+1,t+1+num);
//cout<<t[1].z<<endl;
rep(1,num,i)
{
int x=t[i].x;
int y=t[i].y;
int id=id(x,y);
rep(0,3,k)
{
int xx=dx[k]+x;
int yy=dy[k]+y;
if(xx<1||yy<1||xx>n||yy>m)continue;
if(!a[id(xx,yy)])continue;
int w1=getfather(id(xx,yy));
if(w1==id)continue;
f[w1]=id;add(id,w1);
}
a[id]=t[i].z;
}
rt=id(t[num].x,t[num].y);
//put(rt);
//cout<<getfather(1)<<endl;
dfs(rt);dp(rt,rt);
while(q.size()&&k)
{
ans-=q.top();
cnt=cnt^ans;
q.pop();--k;
}
putl(cnt);
return 0;
}
7.28 NOI模拟赛 H2O 笛卡尔树 并查集 贪心 长链剖分的更多相关文章
- 6.28 NOI模拟赛 好题 状压dp 随机化
算是一道比较新颖的题目 尽管好像是两年前的省选模拟赛题目.. 对于20%的分数 可以进行爆搜,对于另外20%的数据 因为k很小所以考虑上状压dp. 观察最后答案是一个连通块 从而可以发现这个连通块必然 ...
- 7.29 NOI模拟赛 题答 npc问题 三染色 随机 贪心
LINK:03colors 这道题虽然绝大多数的人都获得了满分 可是我却没有. 老师讲题的时候讲到了做题答的几个技巧 这里总结一下. 数据强度大概为n=5000,m=60000的随机数据. 老师说:一 ...
- 2019 蓝桥杯国赛 B 组模拟赛 E 蒜头图 (并查集判环)
思路: 我们看条件,发现满足条件的子图无非就是一些环构成的图, 因为只有形成环,才满足边的两个点都在子图中,并且子图中节点的度是大于0的偶数. 那么如果当前有k个环,我们可以选2^k-1个子图,为什么 ...
- 2019ICPC南昌邀请赛网络赛 I. Max answer (单调栈+线段树/笛卡尔树)
题目链接 题意:求一个序列的最大的(区间最小值*区间和) 线段树做法:用单调栈求出每个数两边比它大的左右边界,然后用线段树求出每段区间的和sum.最小前缀lsum.最小后缀rsum,枚举每个数a[i] ...
- 【BZOJ 2957】楼房重建&&Codechef COT5 Count on a Treap&&【NOIP模拟赛】Weed 线段树的分治维护
线段树是一种作用于静态区间上的数据结构,可以高效查询连续区间和单点,类似于一种静态的分治.他最迷人的地方在于“lazy标记”,对于lazy标记一般随我们从父区间进入子区间而下传,最终给到叶子节点,但还 ...
- POJ 1785 Binary Search Heap Construction(裸笛卡尔树的构造)
笛卡尔树: 每个节点有2个关键字key.value.从key的角度看,这是一颗二叉搜索树,每个节点的左子树的key都比它小,右子树都比它大:从value的角度看,这是一个堆. 题意:以字符串为关键字k ...
- [模板] 笛卡尔树 && RMQ
话说我noip之前为什么要学这种东西... 简介 笛卡尔树(Cartesian Tree) 是一种二叉树, 且同时具有以下两种性质: 父亲节点的值大于/小于子节点的值; 中序遍历的结果为原序列. 笛卡 ...
- [hdu1506 Largest Rectangle in a Histogram]笛卡尔树
题意:http://acm.hdu.edu.cn/showproblem.php?pid=1506 如图,求最大的矩形面积 思路: 笛卡尔树:笛卡尔树是一棵二叉树,树的每个节点有两个值,一个为key, ...
- codevs2178 表达式运算Cuties[笛卡尔树]
2178 表达式运算Cuties 时间限制: 1 s 空间限制: 32000 KB 题目等级 : 大师 Master 题解 查看运行结果 题目描述 Description 给出一个表达 ...
随机推荐
- HotSpot的类模型(3)
上一篇 HotSpot的类模型(2) 介绍了类模型的基础类Klass的重要属性及方法,这一篇介绍一下InstanceKlass及InstanceKlass的子类. 2.InstanceKlass类 每 ...
- thinkphp将对象变成一维数组?
thinkphp使用select查询出的数据为二维数组,如果想将二维数组转一维,可以使用: $x为二维数组对象 php版本要大于5.5.0 $userid_array = array_column($ ...
- HTTP响应头拆分/CRLF注入详解
转自:https://blog.csdn.net/gstormspire/article/details/8183598 https://blog.csdn.net/cqf539/article/de ...
- Centos 6.4最小化安装后的优化(2)
1.关闭不必要的服务 众所周知,服务越少,系统占用的资源就会越少,所以应当关闭不需要的服务器.首先可以先看下系统中存在哪些已经开启了的服务.查看命令如下: ntsysv 下面列出的是需要启动的服务器, ...
- C#联合WINCC之数据通信
[公众号dotNet工控上位机:thinger_swj] 在工控领域中,WINCC仍然占有很大的市场份额.很多时候我们说学习C#开发上位机可以取代传统的组态软件,两者就像冤家一样,然而,即使是冤家,也 ...
- 数据可视化之powerBI入门(九)PowerBI数据建模:其实一点都不高深
https://zhuanlan.zhihu.com/p/64149834 数据建模并没有那么高深,你同样可以学会!这篇文章通过一个实例创建一个简单的数据建模,并引出两个重要的概念:度量值和DAX. ...
- 深度理解SpringIOC,面试你根本不需要慌!
文章已托管到GitHub,大家可以去GitHub查看阅读,欢迎老板们前来Star! 搜索关注微信公众号 码出Offer 领取各种学习资料! 深度理解Spring IOC(控制反转) 一.IOC概述 I ...
- day4:运算符
1.算术运算符:+ - * / // % ** 注意点:1./ 除法,结果为小数 2.// 地板除,返回整数 3.如果被除数或者除数是一个小数,结果加上.0 2.比较运算符:< > & ...
- Apache Avro & Avro Schema简介
为什么需要schema registry? 首先我们知道: Kafka将字节作为输入并发布 没有数据验证 但是: 如果Producer发送了bad data怎么办? 如果字段被重命名怎么办? 如果数据 ...
- TCP 进阶
转自: https://www.cnblogs.com/caoyusongnet/p/9087633.html 一. 端口号 标准的端口号由 Internet 号码分配机构(IANA)分配.这组数字被 ...