bzoj1805: [Ioi2007]Sail 船帆
可以发现旗杆的顺序是没有用的,对于每列,它的答案是它的最大值mx*(mx+1)/2
高度由小到大排序旗杆,问题可以转化为在前h行选k个最小的值
考虑激情splay乱搞(我只会splay......)
设树中序遍历第i个点的d值表示当前最后一个旗帜上面的数字为i-1的列的数量
我们可以二分一下求出我们要利用到第几个点x,对于x之前的点,他们的d值都要全部送给后一个点
所以我们可以删掉x这个点,并在最前面加一个点,这就相当于整体向右移动了一位
对于x这个点单独处理,删除前计算出留在x的数目和给x+1的数目,处理完以后再单独添加
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long LL; struct trnode
{
int f,son[],c,d,s;
}tr[];int trlen,root,cnt;
void update(int x)
{
int lc=tr[x].son[],rc=tr[x].son[];
tr[x].c=tr[lc].c+tr[rc].c+;
tr[x].s=tr[lc].s+tr[rc].s+tr[x].d;
}
void rotate(int x,int w)
{
int f=tr[x].f,ff=tr[f].f;
int R,r; R=f,r=tr[x].son[w];
tr[R].son[-w]=r;
if(r!=)tr[r].f=R; R=ff,r=x;
if(ff!=)
{
if(tr[R].son[]==f)tr[R].son[]=x;
else tr[R].son[]=x;
}
tr[r].f=R; R=x,r=f;
tr[R].son[w]=r;
tr[r].f=R; update(f);
update(x);
}
void splay(int x,int rt)
{
while(tr[x].f!=rt)
{
int f=tr[x].f,ff=tr[f].f;
if(ff==rt)
{
if(tr[f].son[]==x)rotate(x,);
else rotate(x,);
}
else
{
if(tr[f].son[]==x&&tr[ff].son[]==f){rotate(f,);rotate(x,);}
else if(tr[f].son[]==x&&tr[ff].son[]==f){rotate(f,);rotate(x,);}
else if(tr[f].son[]==x&&tr[ff].son[]==f){rotate(x,);rotate(x,);}
else if(tr[f].son[]==x&&tr[ff].son[]==f){rotate(x,);rotate(x,);}
}
}
if(x!=)
{
update(x);
if(rt==)root=x;
}
}
//~~~~~~~~~~~~~~~~~~~~~~~in~~~~~~~~~~~~~~~~~~~~~~~~~~~~
int FindFront()
{
int f=root;
while(tr[f].son[]!=)f=tr[f].son[];
return f;
}
int FindBehind()
{
int f=root;
while(tr[f].son[]!=)f=tr[f].son[];
return f;
}
int findkth(int k)
{
int x=root;k++;
if(k==)return ;
while()
{
int lc=tr[x].son[],rc=tr[x].son[];
if(tr[lc].c>=k)x=lc;
else if(tr[lc].c+<k)k-=tr[lc].c+,x=rc;
else return x;
}
}
//~~~~~~~~~~~~~~~~~~~~Find~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void add(int d,int f,int w)
{
int x=++trlen;
tr[x].f=f;tr[x].c=;tr[x].d=d;tr[x].s=d;
tr[x].son[]=tr[x].son[]=;
if(f!=)tr[f].son[w]=x;
}
void InsInFront(int d)
{
if(root==)add(d,,),root=trlen;
else add(d,FindFront(),);
splay(trlen,);
}
void InsInBehind(int d)
{
if(root==)add(d,,),root=trlen;
else add(d,FindBehind(),);
splay(trlen,);
}
void del(int x)
{
splay(x,);
if(tr[x].son[]==&&tr[x].son[]==)root=;
else if(tr[x].son[]!=&&tr[x].son[]==){root=tr[x].son[];tr[root].f=;}
else if(tr[x].son[]==&&tr[x].son[]!=){root=tr[x].son[];tr[root].f=;}
else
{
int y=tr[x].son[];
while(tr[y].son[]!=)y=tr[y].son[];
splay(y,x); int R=y,r=tr[x].son[];
tr[R].son[]=r;
tr[r].f=R; root=y;tr[root].f=;
update(y);
}
}
//~~~~~~~~~~~~~~~~~~~~~~~out~~~~~~~~~~~~~~~~~~~~~~~~~ //----------------------------------------------------------------------------------------------- LL ans,cc;
void dfs(int x)
{
if(tr[x].son[]!=)dfs(tr[x].son[]);
ans+=(cc-)*cc/*tr[x].d;cc++;
if(tr[x].son[]!=)dfs(tr[x].son[]);
} struct node{int h,k;}a[];
bool cmp(node n1,node n2){return n1.h<n2.h;}
int main()
{
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
int n;
scanf("%d",&n);
for(int i=;i<=n;i++)
scanf("%d%d",&a[i].h,&a[i].k);
sort(a+,a+n+,cmp);
a[].h=; trlen=,root=;
tr[].f=;tr[].c=;tr[].d=;tr[].s=;
tr[].son[]=tr[].son[]=;
InsInFront();cnt=;
for(int i=;i<=n;i++)
{
int fr=FindFront();
tr[fr].d+=a[i].h-a[i-].h;
splay(fr,); int l=,r=cnt,k;
while(l<=r)
{
int mid=(l+r)/;
int x=findkth(mid);splay(x,);
if(tr[tr[x].son[]].s+tr[x].d>=a[i].k)
{
r=mid-;
k=mid;
}
else l=mid+;
} int x=findkth(k-);splay(x,);
int s2=a[i].k-tr[tr[x].son[]].s-tr[x].d;//送给后一个点的值
if(k==cnt)cnt++,InsInBehind(s2);
else
{
int y=findkth(k+);
tr[y].d+=s2;splay(y,);
} x=findkth(k);
int s1=tr[x].d-s2;//留给自己的值
del(x);InsInFront();
x=findkth(k);
tr[x].d+=s1;splay(x,);
} ans=;cc=;dfs(root);
printf("%lld\n",ans);
return ;
}
bzoj1805: [Ioi2007]Sail 船帆的更多相关文章
- BZOJ1805[Ioi2007]Sail船帆——线段树+贪心
题目描述 让我们来建造一艘新的海盗船.船上有 N个旗杆,每根旗杆被分成单位长度的小节.旗杆的长度等于它被分成的小节的数目.每根旗杆上会挂一些帆,每张帆正好占据旗杆上的一个小节.在一根旗杆上的帆可以任意 ...
- BZOJ.1805.[IOI2007]sail船帆(贪心 线段树)
BZOJ 洛谷 首先旗杆的顺序没有影响,答案之和在某一高度帆的总数有关.所以先把旗杆按高度排序. 设高度为\(i\)的帆有\(s_i\)个,那么答案是\(\sum\frac{s_i(s_i-1)}{2 ...
- [BZOJ 1805] Sail 船帆
Link: BZOJ 1805 传送门 Solution: 一道思路比较巧的线段树的题目 首先可以发现,答案和顺序是没有关系的,都是$\sum_{i=1}^n {H_i∗(H_i−1)/2}$. 那么 ...
- [IOI2007] sails 船帆
显然答案与杆的顺序无关(按每个高度考虑). 从高到低考虑杆,设此时的状态为\(S\),\(S[i]\)是高度\(i\)的帆的数目,初始全为\(0\),当前杆的高度为\(h\),杆上需要放置的帆的数目为 ...
- luoguP4647 [IOI2007] sails 船帆
https://www.luogu.org/problemnew/show/P4647 首先发现答案与顺序无关,令 $ x_i $ 表示高度为 $ i $ 的那一行帆的个数,第 $ i $ 行对答案的 ...
- bzoj AC倒序
Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...
- sail.js学习 - 安装篇
导言: 最近在学习sails.js(http://sailsjs.org/),因为用的人不多,资料较少,故写些自己的学习过程.因自己也是初学node.js,有问题大家指出. 介绍: sails.js的 ...
- Codeforces Round #180 (Div. 2) B. Sail 贪心
B. Sail 题目连接: http://www.codeforces.com/contest/298/problem/B Description The polar bears are going ...
- [Ioi2007]Miners 矿工配餐(BZOJ1806)
[Ioi2007]Miners 矿工配餐 Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 214 Solved: 128 Description 现有两 ...
随机推荐
- JS函数assign
Object函数提供了一个叫做assign的函数,用来合并多个对象. Object.assign(...): 你可以传递多个对象给该函数,这些对象中的自有且可枚举的属性,会被拷贝给第一个对象. var ...
- CMU-准备
TOEFL成绩90分以上,GPA大于3.0,GRE1250分以上(不做明确要求) 申请条件:GRE成绩,建议有专科成绩;托福250,雅思7.0;简历;3封推荐信 TOEFL(The Test of E ...
- vue-quill-editor + element-ui upload实现富文本图片上传
代码贴上 <template> <div class="quill-editor-example"> <div class="box&quo ...
- WebService接口数据传输加密
1.加密流程 客服端--->加密文本------>服务端接收到加密文本,通过固定加密密文进行解密,然后做相应处理------------>返回结果 2.固定密文创建 密文创建有很多种 ...
- nfs服务权限配置
nfs服务权限配置 1. 查看系统是否已经安装了服务Rpm -qa | grep nfs 2. 启动服务,并且开机自动运行Systemctl start nfsSystemctl enabled nf ...
- Python初学者容易忽略的一些细节
1.Python中当让给变量1赋值上变量2的值时,变量1直接指向值在内存中存储的地址,即变量1存储的是变量2的值而不是指向变量 2."""的用法 1.多行注释 2.多行输 ...
- BZOJ 3916 [Baltic2014]friends
[题解] 暴力枚举添加字符的位置,然后判断去掉这个位置的字符串是否有由两个相同的串拼接而成.本题的n的范围为200W,暴力判断会TLE,所以要使用哈希. #include<cstdio> ...
- C++ 输入外挂
inline int read() { int x=0;char ch=getchar(); while(ch<'0'||ch>'9')ch=getchar(); while(ch> ...
- ACM-ICPC 2018 徐州赛区网络预赛 J. Maze Designer
传送门:https://nanti.jisuanke.com/t/31462 本题是一个树上的问题:结点间路径问题. 给定一个有N×M个结点的网格,并给出结点间建立墙(即拆除边)的代价.花费最小的代价 ...
- DESEncrypt对称加密解密
分享一个很好用的DESEncrypt对称加密解密的类 using System; using System.Security.Cryptography; using System.Text; usin ...