T1

Description

给定一个序列,初始为空。依次将$1-n$插入序列,其中$i$插到当前第$a_i$个数的右边($a_i=0$表示插到序列最左边)。求最终序列。

Input

第一行一个整数$n$。第二行$n$个正整数$a_1-a_n$。

Output

输出一行$n$个整数表示最终序列,数与数之间用一个空格隔开。

Sample Input

5
0 1 1 0 3

Sample Output

4 1 3 5 2

HINT

$n<=10^6,0\;\leq\;a_i<i$.

Solution

首先,看到这种题显然倒着处理比较容易。

其次,这题$O(nlogn)$能过(可是我的机子跑不过啊!!!)

所以可以用线段树维护当前区间剩余可填格子的个数,每次寻找第$a[i]+1$个空格在哪。

#include<cmath>
#include<ctime>
#include<stack>
#include<queue>
#include<cstdio>
#include<vector>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define N 5000005
using namespace std;
struct linetree{
int l,r,s,b;
}lt[N];
int a[N],s[N],ans[N],n;
inline int read(){
int ret=;char c=getchar();
while(!isdigit(c))
c=getchar();
while(isdigit(c)){
ret=ret*+c-'';
c=getchar();
}
return ret;
}
inline void build(int u,int l,int r){
lt[u].l=l;lt[u].r=r;lt[u].s=r-l+;
if(l==r) return;
int lef=u<<,rig;rig=lef|;
int mid=(l+r)>>;
build(lef,l,mid);build(rig,mid+,r);
}
inline int ask(int u,int k){
if(lt[u].l==lt[u].r)
return lt[u].l;
int l=u<<,r;r=l|;
if(lt[u].s==k)
if(lt[l].s==k) ask(l,k);
else ask(r,k-lt[l].s);
else if(lt[l].s>=k) ask(l,k);
else ask(r,k-lt[l].s); }
inline bool chk(linetree l,int x){
return l.l<=x&&l.r>=x;
}
inline void dec(int u,int x){
if(chk(lt[u],x)) lt[u].s--;
if(lt[u].l<lt[u].r){
int l=u<<,r;r=l|;
if(chk(lt[l],x)) dec(l,x);
else if(chk(lt[r],x)) dec(r,x);
}
else lt[u].b=true;
}
inline void init(){
n=read();build(,,n);
for(int i=;i<=n;i++)
a[i]=read();
for(int i=n,k;i;i--){
k=ask(,a[i]+);
ans[k]=i;dec(,k);
}
for(int i=;i<=n;i++)
printf("%d ",ans[i]);
printf("\n");
}
int main(){
freopen("sequence.in","r",stdin);
freopen("sequence.out","w",stdout);
init();
fclose(stdin);
fclose(stdout);
return ;
}

T2

Description

有$n$个物品和一个大小为$m$的背包,每个物品有大小和价值,求背包里最多能放下多少价值的物品。

Input

第一行两个整数$n,m$。接下来$n$行每行两个整数$x_i,w_i$,表示第$i$个物品的大小和价值。

Output

一行一个整数表示最大价值。

Sample Input

5 100
95 80

4 18

3 11

99 100

2 10

Sample Output

101

HINT

$n\;\leq\;40,0\;\leq\;m\;\leq\;10^{18},0\;\leq\;x_i,w_i\;\leq\;10^{15}$.

Solution

显然数据不适合$dp$,由于$n$比较小,所以会想到折半搜索。

把前$n/2$个物品的所有方案存下来,删去明显劣的。

再枚举剩余的物品,对于每种方案,二分求与前$n/2$个物品能组成的最大价值。

(我以前有做过类似的题,只不过求的是是否存在总价值为$w$的方案,然而这题当时我还没想出来$QAQ$)

#include<cmath>
#include<ctime>
#include<stack>
#include<queue>
#include<cstdio>
#include<vector>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define N 45
#define M 2000000
using namespace std;
typedef long long ll;
struct thing{
ll x,w;
}a[N],b[M];
int n,nn,cnt=-,tot=;
ll m,ans;
inline ll search(ll m){
if(m<b[].x) return ;
int l=,r=tot,mid;
while(l<r){
mid=l+r+>>;
if(b[mid].x<=m) l=mid;
else r=mid-;
}
return b[l].w;
}
inline void dfs1(int u,ll sw,ll sx){
if(u>nn){
b[++cnt]=(thing){sx,sw};
return;
}
dfs1(u+,sw,sx);
if(sx+a[u].x<=m)
dfs1(u+,sw+a[u].w,sx+a[u].x);
}
inline void dfs2(int u,ll sw,ll sx){
if(u>n){
sw+=search(m-sx);
ans=max(ans,sw);
return;
}
dfs2(u+,sw,sx);
if(sx+a[u].x<=m)
dfs2(u+,sw+a[u].w,sx+a[u].x);
}
inline bool cmp(thing x,thing y){
if(x.x!=y.x) return x.x<y.x;
return x.w>y.w;
}
inline void init(){
scanf("%d%lld",&n,&m);
for(int i=;i<=n;++i)
scanf("%lld%lld",&a[i].x,&a[i].w);
nn=n>>;dfs1(,,);
sort(b+,b++cnt,cmp);
for(int i=;i<=cnt;i++)
if(b[i].x>b[i-].x) b[++tot]=b[i];
for(int i=;i<=tot;i++)
b[i].w=max(b[i].w,b[i-].w);
dfs2(nn+,,);
printf("%lld\n",ans);
}
int main(){
freopen("pack.in","r",stdin);
freopen("pack.out","w",stdout);
init();
fclose(stdin);
fclose(stdout);
return ;
}

T3

Description

有一棵线段树,根为$[1,n]$,有所不同的是,每个节点$[l,r]$的孩子为$[l,k]$,$[k+1,r]$,其中$l\;\leq\;k<r$且$k$的值由你决定。给定$m$个区间,定义区间$[a_i,b_i]$会访问到节点$[l,r]$仅当他们会相交。求每次访问的结点个数之和的最小值。

Input

第一行两个整数$n,m$,接下来$m$行每行两个整数$a_i,b_i$。

Output

一行一个整数表示答案。

Sample Input

6 6
1 4

2 6

3 4

3 5

2 3

5 6

Sample Output

40

HINT

$n\;\leq\;5000,m\;\leq\;10^5$

Solution

$f[i][j]$表示节点$[i,j]$的子树中被访问的最少次数,$s[i][j]$表示与节点$[i,j]$相交的区间数。

$f[i][j]=min{f[i][k]+f[k+1][j]}+s[i][j]\;(i\;\leq\;k<j)$。

直接枚举是$O(n^3)$,显然会$T$。

用四边形不等式优化能压到$O(n^2)$.


以下为不保证正确性的证明,不喜请跳过

①当$a\;\leq\;b<c\;\leq\;d$时,易证$s[a][c]+s[b][d]=s[b][c]+s[a][d]$,$s[\;][\;]$满足四边形不等式。

②当$[i,j]$属于$[i',j']$时,$s[i,j]\;\leq\;s[i',j'],s[\;][\;]$满足区间包含关系单调。

因为同时满足①②,所以$f[\;][\;]$满足四边形不等式。

记使$f[i][j]$取最小值时的$k$为$g[i][j]$,则$g[i][j-1]\;\leq\;g[i][j]\;\leq\;g[i+1][j]$。

易证枚举$k$的总时间复杂度为$O(n)$。


#include<cmath>
#include<ctime>
#include<stack>
#include<queue>
#include<cstdio>
#include<vector>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define N 5005
#define M 10005
#define INF 500000005
using namespace std;
int f[N][N],g[N][N],s[N][N],n,m;
inline int read(){
int ret=;char c=getchar();
while(!isdigit(c))
c=getchar();
while(isdigit(c)){
ret=ret*+c-'';
c=getchar();
}
return ret;
}
inline void init(){
n=read();m=read();
for(int i=,j,k;i<=m;++i){
j=read();k=read();
++s[k][j];
}
for(int i=;i<=n;++i)
for(int j=;j<=n;++j)
s[i][j]+=s[i][j-];
for(int i=n;i;--i)
for(int j=;j<=n;++j)
s[i][j]+=s[i+][j];
for(int i=;i<=n;++i){
f[i][i]=s[i][i];
g[i][i]=i;
}
for(int l=;l<n;++l){
for(int i=,j;i+l<=n;++i){
j=i+l;f[i][j]=INF;
for(int k=g[i][j-];k<=g[i+][j];++k){
if(f[i][k]+f[k+][j]<f[i][j]){
f[i][j]=f[i][k]+f[k+][j];
g[i][j]=k;
}
}
f[i][j]+=s[i][j];
}
}
printf("%d\n",f[][n]);
}
int main(){
freopen("segment.in","r",stdin);
freopen("segment.out","w",stdout);
init();
fclose(stdin);
fclose(stdout);
return ;
}

[日常训练]常州集训day7的更多相关文章

  1. [日常训练]常州集训day8

    T1 Description 给定一个长度为$n$的正整数序列$a$.可以将序列分成若干段,定义第$i$段的权值$x_i$为这一段中所有数的最大值,特殊地,$x_0=0$.求$\sum_{i=1}^{ ...

  2. [日常训练]常州集训day5

    T1 Description 小$W$和小$M$一起玩拼图游戏啦~ 小$M$给小$M$一张$N$个点的图,有$M$条可选无向边,每条边有一个甜蜜值,小$W$要选$K$条边,使得任意两点间最多有一条路径 ...

  3. [日常训练]常州集训day3

    T1 Description 有$K$个石子,石子只能放在$N$条水平线与$M$条竖直线构成的网格的交点上. 求用$K$个石子最多能找到多少四边平行于坐标轴的长方形,它的四个角上都恰好放着一枚石子. ...

  4. [日常训练]常州集训day2

    T1 Description 给定$N$个点,问这$N$个点能构成的三角形个数. Input 第一行一个整数$N$,代表点数. 接下来$N$行,每行两个非负整数$X,Y$,表示一个点的坐标. Outp ...

  5. 「2017 山东三轮集训 Day7 解题报告

    「2017 山东三轮集训 Day7」Easy 练习一下动态点分 每个点开一个线段树维护子树到它的距离 然后随便查询一下就可以了 注意线段树开大点... Code: #include <cstdi ...

  6. 【LOJ6077】「2017 山东一轮集训 Day7」逆序对 生成函数+组合数+DP

    [LOJ6077]「2017 山东一轮集训 Day7」逆序对 题目描述 给定 n,k ,请求出长度为 n的逆序对数恰好为 k 的排列的个数.答案对 109+7 取模. 对于一个长度为 n 的排列 p ...

  7. 「日常训练」ZgukistringZ(Codeforces Round #307 Div. 2 B)

    题意与分析(CodeForces 551B) 这他妈哪里是日常训练,这是日常弟中弟. 题意是这样的,给出一个字符串A,再给出两个字符串B,C,求A中任意量字符交换后(不限制次数)能够得到的使B,C作为 ...

  8. 2017 山东二轮集训 Day7 国王

    2017 山东二轮集训 Day7 国王 题目大意 给定一棵树,每个点有黑白两种颜色,定义一条简单路径合法当且仅当路径上所有点黑色与白色数量相等,求有多少非空区间 \([L,R]\) ,使得所有编号 \ ...

  9. loj #6077. 「2017 山东一轮集训 Day7」逆序对

    #6077. 「2017 山东一轮集训 Day7」逆序对   题目描述 给定 n,k n, kn,k,请求出长度为 n nn 的逆序对数恰好为 k kk 的排列的个数.答案对 109+7 10 ^ 9 ...

随机推荐

  1. apache网站访问缓慢的处理记录

    朋友在阿里云上开通了一台ubuntu服务器(2G内存,2核CPU),用apache搭建了一个公众号网站.网站初期,他没有做相应的优化,在后续公众号推广活动时,网站并发突增,访问十分缓慢.登陆服务器,具 ...

  2. Docker容器概念讲解

    Docker 是 PaaS 提供商 dotCloud 开源的一个基于 LXC 的高级容器引擎,源代码托管在 Github 上, 基于go语言并遵从Apache2.0协议开源. Docker是通过内核虚 ...

  3. MySQL与MongoDB的操作对比,以及区别

    MySQL与MongoDB都是开源的常用数据库,但是MySQL是传统的关系型数据库,MongoDB则是非关系型数据库,也叫文档型数据库,是一种NoSQL的数据库.它们各有各的优点,关键是看用在什么地方 ...

  4. java多线程系类:基础篇:04synchronized关键字

    概要 本章,会对synchronized关键字进行介绍.涉及到的内容包括:1. synchronized原理2. synchronized基本规则3. synchronized方法 和 synchro ...

  5. DocOptimizer 0.9.0 Beta Released

    DocOptimizer 是一个文档优化工具,它通过移除Excel中多余的单元格:将嵌入的OLE替换成图片:移除文档中的隐藏信息:优化文档中的图片等等手段,将Office或PDF文件压缩20%-90% ...

  6. QT 网络编程二(UDP版本)

    QT的UdpSocket接收消息使用原则 第一步:new一个UdpSocket 第二步:调用UdpSocket的bind方法,同时指定端口号 第三步:使用connect将接收消息函数和UdpSocke ...

  7. MVC-RedirectToAction跳转到其他Area

    mvc使用Area分区开发后,存在不同Area之间的跳转,需要为每个区间添加Area规则,如下: using System.Web.Mvc; namespace web.Areas.FrameSet ...

  8. TinyFrame尾篇:整合Spring AOP实现用户认证

    创建Manager用户验证表 这一篇主要讲解使用AOP对用户操作进行验证,如果通过验证,则继续执行,反之,则不能执行.其思想和上一篇完全一致. 由于需要用到用户认证,所以我们新建一个Manager实体 ...

  9. Javascript中判断数组的正确姿势

    在 Javascript 中,如何判断一个变量是否是数组? 最好的方式是用 ES5 提供的 Array.isArray() 方法(毕竟原生的才是最屌的): var a = [0, 1, 2]; con ...

  10. mvc5+ef6+Bootstrap 项目心得--创立之初

    1.mvc5+ef6+Bootstrap 项目心得--创立之初 2.mvc5+ef6+Bootstrap 项目心得--身份验证和权限管理 3.mvc5+ef6+Bootstrap 项目心得--WebG ...