1. 程式人生 > >Codeforces Round #470 (rated, Div. 2, based on VK Cup 2018 Round 1)

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

本來大晚上的不準備打的。。。後來打完遊戲發現還一個小時。然後就涼了
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; }