您的位置:首页 > 其它

Codeforces Round #470 (rated, Div. 2, based on VK Cup 2018 Round 1)

2018-03-11 02:02 537 查看
本来大晚上的不准备打的。。。后来打完游戏发现还一个小时。然后就凉了

A 签到题。

除了WS二连的No,统统填上D Yes。

C 开的第二道题,过得人相对其他的多,不知道他们是不是各种特判过得。。。。

题意是:给两个序列,A,B;

A是每天新增的雪堆的数,B是每天所有雪堆要减少的数,减到0为止;

求每一天所有雪堆减少的数量,

题意很简单,n^2的写法是,枚举每一个雪堆,然后遍历后面的天k,给他们加上B[k],知道雪堆为0;

对于n=1e5,如果数据不是很极端的话应该能过,

不过过的人不多,所以,肯定有这种数据

100000000 1000000000 1000000000……………….

1 1 1……………………

这样就爆炸了。

然后最少要写一个nlogn的算法。

logn 一般就是二分,还有树状结构,实际上也是二分。

然后我就想到预处理前缀和,然后对前缀和二分查找,然后在覆盖的区间上的标记+1;多出来的一些直接加到ans数组上。

然后最后用树状数组对标记进行处理,单点查询。

最后的结果就是,ans[i]+tag[i]*T[i]

调试的坑点是,二分和更新树状数组的时候。在代码里有些。

时间关系,代码没交上。睡觉了

#include <iostream>
#include <cstdio>
#include <cstring>
#define mem(x) memset(x,0,sizeof(x))
using namespace std;
typedef long long ll;
const int N=1e5+10;
ll sum
;//这里全都要开longlong 不然就wa了。我也不知道为什么
int n;
ll A
;
ll T
;
ll c
;
ll ans
;
int low_b(int x,int y,ll v)
{
int s=x;
int m;
while(x<y)
{
m=x+(y-x)/2;
if(sum[m]-sum[s-1]>=v) y=m;
else x=m+1;
}
if(v==sum[x]-sum[s-1])//这里注意返回low_b+1的位置方便后序操作
return x+1;
else return x;
}

int lowbit(int x)
{
return (x&-x);
}
void update(int x,int y)
{
while (x<=n)
{
c[x]+=y;
x+=lowbit(x);
}
}
int query(int x)
{
int ans=0;
while (x>0)
{
ans+=c[x];
x-=lowbit(x);
}
return ans;
}

int main()
{
while(cin>>n)
{
for(int i=1;i<=n;i++)
cin>>A[i];
for(int i=1;i<=n;i++)
cin>>T[i];
sum[1]=T[1];
sum[0]=0;
for(int i=2;i<=n;i++)
sum[i]=T[i]+sum[i-1];
mem(ans);
mem(c);
for(int i=1;i<=n;i++)
{
int tt = low_b(i,n+1,A[i]);
ans[tt]+=A[i]-(sum[tt-1]-sum[i-1]);//[i,tt-1]没用完的雪,给tt加上
if(tt!=i)//不一样就更新
{
update(i,1);
update(tt,-1);
}
}
for(int i=1;i<=n;i++)
{
cout<<(T[i]*query(i)+ans[i])<<(i==n?"\n":" ");
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐