2017 济南综合班 Day 7
a

两个指针L、R
R开始指向恰好[R,n]有不超过k个逆序对的地方
随着L的右移,R指针只会右移
逆序对有2部分
1、L左侧与其他位置形成的逆序对
2、R右侧与其他位置形成的逆序对
用树状数组分别维护这两部分
同时维护当前逆序对个数
每次L右移,新的L会增加与L左侧的逆序对和与R右侧的逆序对
每次R右移,R的消失会减少R右侧的逆序对和与L左侧的逆序对
#include<cstdio>
#include<algorithm>
#define N 100012
using namespace std;
int tot;
int a[N],hash[N];
int c1[N],c2[N];
int query1(int x)
{
int sum=; while(x) { sum+=c1[x]; x-=x&-x; } return sum;
}
int query2(int x)
{
int sum=; while(x) { sum+=c2[x]; x-=x&-x; } return sum;
}
void add1(int x,int y)
{
while(x<=tot) { c1[x]+=y; x+=x&-x; }
}
void add2(int x,int y)
{
while(x<=tot) { c2[x]+=y; x+=x&-x; }
}
int main()
{
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
int n,k;
long long ans=,cnt=;
scanf("%d%d",&n,&k);
for(int i=;i<=n;i++) scanf("%d",&a[i]),hash[i]=a[i];
sort(hash+,hash+n+);
tot=unique(hash+,hash+n+)-(hash+);
for(int i=;i<=n;i++) a[i]=lower_bound(hash+,hash+tot+,a[i])-hash;
int R=n;
while(R>=)
{
add2(a[R],);
cnt+=query2(a[R]-);
R--;
}
R++;
for(int L=;L<n;L++)
{
if(L==R)
{
cnt=cnt-(L--query1(a[R]))-query2(a[R]-);
add2(a[R++],-);
}
cnt=cnt+L--query1(a[L])+query2(a[L]-);
add1(a[L],);
while(cnt>k && R<=n )
{
cnt=cnt-(L-query1(a[R]))-query2(a[R]-);
add2(a[R++],-);
}
if(cnt<=k) ans+=n-R+;
}
printf("%I64d",ans);
}
b

状态压缩式的搜索
但一开始分明是按着DP做的
于是就写出了个又像DP又像bfs的代码
两个结论:
1、成功搞事的前提是 a中除1之外的数 都能由前面的2个数相加得到(可以是2个相同的数)
2、最优解b中的数一定可以是a中的某些数
先判断a是否符合结论1,同时记录a中的每个数可以由哪两个数相加得到
N只有23,将N状态压缩,每一位表示当前状态b中有没有a中的这个数
设state[i][] 表示当前第i次搞事,b中可以有的a的状态
那么state[i][]可以由state[i-1][]转移的条件是
若a[p]+a[q]=a[i] ,state[i-1][]这个状态含有任意一对p、q
所以枚举state[i-1][]中的每一种状态,若这个状态可以转移
不管选哪对p、q,总要用i替换掉这个状态中的某一个位置或者是新增一个位置
替换:设当前状态为j,要替换掉第k位,新的状态为 j^k|i
新增:j^i
最后枚举state[n][]中的每一种状态,1的个数取最少就是答案
优化1:滚动数组
优化2:状态判重,新开一个数组vis[],int类型,用时间戳的方式判重,避免每次清空
优化3:类似于可行性剪枝,再枚举i-1的状态时,加上
if(minans<当前状态已经用的a的数量) continue;
minans=min(minans,当前状态已经用的a的数量+最多还能用的a的数量);
#include<cstdio>
#include<algorithm>
#define N 23
using namespace std;
int dp[(<<N)+];
int n,num[N+];
int way[N+][][];
int state[][(<<N)+];
int vis[(<<N)+];
int sum[(<<N)+];
int count(int x)
{
int cnt=;
while(x) cnt+=x&,x>>=;
return cnt;
}
int main()
{
freopen("b.in","r",stdin);
freopen("b.out","w",stdout);
scanf("%d",&n);
for(int i=;i<=n;i++) scanf("%d",&num[i]);
bool can=false;
for(int a=;a<=n;a++)
{
can=false;
for(int b=;b<a;b++)
for(int c=b;c<a;c++)
if(num[a]==num[b]+num[c])
{
can=true;
way[a][][]++;
way[a][way[a][][]][]=b;
way[a][way[a][][]][]=c;
}
if(!can) { printf("-1"); return ; }
}
int tot=<<n;
for(int i=;i<tot;i++) sum[i]=count(i);
int b,c,j,news;
int now=,last=;
int minans=;
state[][]=state[][]=;
for(int a=;a<=n;a++)
{
state[now][]=;
for(int k=;k<=state[last][];k++)
{
j=state[last][k];
if(minans<sum[j]) continue;
minans=min(minans,sum[j]+n-a+);
can=false;
for(int i=;i<=way[a][][];i++)
{
b=way[a][i][];
c=way[a][i][];
if((j & <<b-) && (j & <<c-))
{
can=true;
break;
}
}
if(!can) continue;
for(int i=;i<=n;i++)
if(j & <<i-)
{
news=j ^ <<i- | <<a-;
if(vis[news]!=a)
{
state[now][++state[now][]]=news;
vis[news]=a;
}
}
news=j ^ <<a-;
if(vis[news]!=a)
{
state[now][++state[now][]]=news;
vis[news]=a;
}
}
swap(now,last);
}
int ans=;
for(int i=;i<=state[last][];i++) ans=min(ans,sum[state[last][i]]);
printf("%d",ans);
}
c

所有球无论怎么碰撞,他们的顺序不变
所以先对所有的小球排序
然后枚举相邻两个小球,计算出即将最早碰撞的两个球所需时间t
让所有的球都移动t时间,改变两个球的速度
重复枚举直到没有球会发生碰撞或超过时间
#include<cmath>
#include<cstdio>
#include<algorithm>
using namespace std;
struct node
{
int m,id;
double x,v;
}e[];
bool cmp(node p,node q)
{
return p.x<q.x;
}
bool cmp2(node p,node q)
{
return p.id<q.id;
}
double v1(int i,int j)
{
return ((e[i].m-e[j].m)*e[i].v+*e[j].m*e[j].v)/(e[i].m+e[j].m);
}
double v2(int i,int j)
{
return ((e[j].m-e[i].m)*e[j].v+*e[i].m*e[i].v)/(e[i].m+e[j].m);
}
int main()
{
freopen("c.in","r",stdin);
freopen("c.out","w",stdout);
int n,k;
scanf("%d%d",&n,&k);
for(int i=;i<=n;i++) scanf("%lf%lf%d",&e[i].x,&e[i].v,&e[i].m),e[i].id=i;
sort(e+,e+n+,cmp);
int a,b;
double delta,now,tmp,va,vb ;
while()
{
delta=2e9;
for(int i=;i<n;i++)
for(int j=i+;j<=n;j++)
{
if(e[i].v> && e[j].v> && e[i].v<e[j].v) continue;
if(e[i].v< && e[j].v>) continue;
if(e[i].v< && e[j].v< && e[i].v<e[j].v) continue;
tmp=(e[j].x-e[i].x)/(e[i].v-e[j].v);
if(tmp<delta) delta=tmp,a=i,b=j;
}
if(now+delta>k) break;
for(int i=;i<=n;i++) e[i].x+=delta*e[i].v;
va=v1(a,b);
vb=v2(a,b);
e[a].v=va; e[b].v=vb;
now+=delta;
}
delta=k-now;
for(int i=;i<=n;i++) e[i].x+=delta*e[i].v;
sort(e+,e+n+,cmp2);
for(int i=;i<=n;i++) printf("%.3lf\n",e[i].x);
}
2017 济南综合班 Day 7的更多相关文章
- 2017 济南综合班 Day 6
循环移动 (cyclic.cpp/c/pas) (1s/256M) 问题描述 给出一个字符串S与N个操作.每个操作用三元组(L, R, K)进行描述:操作将字符串第L个到第R个位置构成的子串循环移动K ...
- 2017 济南综合班 Day 5
毕业考试 (exam.cpp/c/pas) (1s/256M) 问题描述 快毕业了,Barry希望能通过期末的N门考试来顺利毕业.如果他的N门考试平均分能够达到V分,则他能够成功毕业.现在已知每门的分 ...
- 2017 济南综合班 Day 4
T1 外星人 二维前缀和 #include<cstdio> #define N 1001 using namespace std; bool v[N][N]; int sum[N][N]; ...
- 2017 济南综合班 Day 3
T1 黑化 题意: 求一个字符串是否可能包含另一个字符串 字符串中的?可以匹配任意字母 可能输出 God bless You! 一定不可能 输出 Game Over! 计算fail数组时,fail数 ...
- 2017 济南综合班 Day 2
木棍(stick) Time Limit:1000ms Memory Limit:128MB 题目描述 LYK有很多木棍,具体的,总共有n根,且每根木棍都有一个长度.为了方便起见,我们可以用一个正 ...
- 2017 济南综合班 Day 1
送分题(songfen) Time Limit:1000ms Memory Limit:128MB 题目描述 LYK喜欢干一些有挑战的事,比如说求区间最大子段和.它知道这个题目有O(n)的做法.于 ...
- 2017 济南精英班 Day1
不管怎么掰都是n*m-1 #include<cstdio> using namespace std; int main() { freopen("bpmp.in",&q ...
- JavaScript脚本语言基础(四)
导读: JavaScript和DOM DOM文档对象常用方法和属性 DOW文档对象运用 JSON数据交换格式 正则表达式 1.JavaScript和DOM [返回] 文档对象模型(Document O ...
- JeeSite(2):导入数据,进入系统
本文的原文连接是: http://blog.csdn.net/freewebsys/article/details/50954485 未经博主同意不得转载. 博主地址是:http://blog.csd ...
随机推荐
- [C++] String Basic
Namespace Declarations A using declaration let us use a name from a namespace without qualify the na ...
- Python中的eval
Python中的eval方法接受一个字符串参数,并且把字符串里面的内容当成Python代码来执行: eval的缺点是执行速度慢,并且会有安全风险
- string && 字符数组
一.string 1. 使用字符串字面值初始化string对象 如:string s1 = "hiya"; string s2("hiya"); 该字面值的最后 ...
- c++ 第五次作业(计算器第三步)
第五次作业 (计算器第三步) 项目源文件地址:calculator 本次作业改进情况 加入多种读入选择 正常输出答案 -a 选项,输出表达式以及值 -f 选项,从指定文件读入,并把答案输出到指定文件 ...
- 内存转储文件调试系统崩溃bug
百度百科:内存转储文件 内存转储是用于系统崩溃时,将内存中的数据转储保存在转储文件中,供给有关人员进行排错分析用途.而它所保存生成的文件就叫做内存转储文件. 内存转储文件也被称作虚拟内存,它是用硬盘里 ...
- TCP/IP 三次握手四次挥手
TCP运输连接 TCP连接建立过程中要解决以下三个问题: (1)要使每一方能够确知双方的存在. (2)要允许双方协商一些参数(如最大窗口值.是否使用窗口扩大选项和时间戳选项以及服务质量等). (3)能 ...
- 【Linux】- Ubutnu UFW防火墙的简单设置
ufw是一个主机端的iptables类防火墙配置工具,比较容易上手.一般桌面应用使用ufw已经可以满足要求了. 安装方法 sudo apt-get install ufw 使用方法 1.启用: sud ...
- C# 压缩组件介绍与入门
1.前言 作为吉日嘎拉权限管理系统最早的一批学习版用户,学了不少东西,在群里面也结识了很多朋友,更重要的是闲余时间,大家都发布很多可靠的外包工作.这次也是由于吉日嘎拉发布了一个有关“压缩文件损坏检测” ...
- Linux和Windows文件路径
linux系统下的文件夹路径和window下的不一样,windows下就需要写成“\\photos"因为java会把第一个"\"当成转义字符给“吃了”.但在linux下就 ...
- Codeforces Round #510 Div. 2 Virtual Participate记
这场打的顺手到不敢相信.如果不是vp的话估计肯定打不到这个成绩. A:最大显然,最小的话每次暴力给最小的+1. #include<iostream> #include<cstdio& ...