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 ...
随机推荐
- [知识库:python-tornado]异步调用中的上下文控制Tornado stack context
异步调用中的上下文控制Tornado stack context https://www.zouyesheng.com/context-in-async-env.html 这篇文章真心不错, 非常透彻 ...
- URAL 1664 Pipeline Transportation(平面图最大流)
Description An oligarch Vovan, as many other oligarchs, transports oil from West Cuckooland to East ...
- Python学习之路2 - 列表和元组
列表 概念:Python内置的一种数据类型是列表:list.list是一种有序的集合,可以随时添加和删除其中的元素. 列表的使用 names = ['zhangsan','lisi','wangwu' ...
- [经典贪心算法]Prim算法
最小生成树的Prim算法也是贪心算法的一大经典应用.Prim算法的特点是时刻维护一棵树,算法不断加边,加的过程始终是一棵树. Prim算法过程: 一条边一条边地加, 维护一棵树. 初始 E = {}空 ...
- LintCode-8.旋转字符串
旋转字符串 给定一个字符串和一个偏移量,根据偏移量旋转字符串(从左向右旋转) 样例 对于字符串 "abcdefg". offset=0 => "abcdefg&qu ...
- <Effective C++>读书摘要--Inheritance and Object-Oriented Design<一>
1.Furthermore, I explain what the different features in C++ really mean — what you are really expres ...
- <Android>列表、网格、画廊视图及适配器的绑定
列表视图和适配器的绑定 列表视图既可以使用ListView组件,也可以继承ListActivity.显示可以是ArrayAdapter,也可以是游标SimpleCursorAdapter,还可以是继承 ...
- osg::Vec2 Vec3 Vec4
osg::Vec2可以用于保存2D纹理坐标. osg::Vec3是一个三维浮点数数组. osg::Vec4用于保存颜色数据.
- 多个表单数据提交下的serialize()应用
在实际开发场景中,难免遇到需要多个表单的数据传递问题. 之所以要进行多表单的数据传递是因为可以进行数据分组,便于数据的维护. 这个时候,出于不依赖jquery的考虑,有一个原生js函数来解决这个问题无 ...
- redis——持久化方式RDB与AOF分析
https://blog.csdn.net/u014229282/article/details/81121214 redis两种持久化的方式 RDB持久化可以在指定的时间间隔内生成数据集的时间点快照 ...