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 现有两 ...
随机推荐
- RocketMQ学习笔记(16)----RocketMQ搭建双主双从(异步复制)集群
1. 修改RocketMQ默认启动端口 由于只有两台机器,部署双主双从需要四个节点,所以只能修改rocketmq的默认启动端口,从官网下载rocketmq的source文件,解压后使用idea打开,全 ...
- jmeter插件之PerfMon
PerfMon是jmeter监控系统资源的一款插件,可以用来监控系统的CPU/内存/IO等性能指标. 一.要准备好的插件:JMeterPlugins-Standard-1.4.0(pwd:cjqd)或 ...
- 03C++基本数据类型
基本数据类型 2.2.1整型数据 短整型(short int) 有符号短整型(signed short int) 无符号短整型(unsigned short int) 一般整型(int) 有符号一般整 ...
- 第三节:执行一些EF的增删改查
针对两表操作 一丶增加 #region 05-增加操作 /// <summary> /// 05-增加操作 /// </summary> /// <param name= ...
- 抓取猫眼电影top100的正则、bs4、pyquery、xpath实现方法
import requests import re import json import time from bs4 import BeautifulSoup from pyquery import ...
- linux shell脚本学习笔记一
一.文件比较运算符-e filename 如果 filename存在,则为真 [ -e /var/log/syslog ]-d filename 如果 filename为目录,则为真 [ -d /tm ...
- HDU - 4810 - Wall Painting (位运算 + 数学)
题意: 从给出的颜料中选出天数个,第一天选一个,第二天选二个... 例如:第二天从4个中选出两个,把这两个进行异或运算(xor)计入结果 对于每一天输出所有异或的和 $\sum_{i=1}^nC_{n ...
- TestNG多线程测试-用xml文件实现
MultiThreadOnXml类: package com.janson.multiThread; import org.testng.annotations.Test; public class ...
- Linux:使用root踢掉其他用户
首先使用w命令查看所有在线用户: 执行命令: pkill -kill -t tty3 再用w命令查看是否已经强制踢掉: TTY 是终端的意思 TTY :0 表示root用户登陆图形化界面的终 ...
- RANS VS LES
Turbulence models