Codeforces Round #470 (rated, Div. 2, based on VK Cup 2018 Round 1)
阿新 • • 發佈:2018-11-10
本來大晚上的不準備打的。。。後來打完遊戲發現還一個小時。然後就涼了
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[N];//這裡全都要開longlong 不然就wa了。我也不知道為什麼
int n;
ll A[N];
ll T[N];
ll c[N];
ll ans[N];
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;
}