演算法馬拉松8 差和問題

2021-07-08 10:17:55 字數 3144 閱讀 1326

差和問題

有乙個集合s,初始狀態下有n個元素,對他進行如下操作:

1、向s裡面新增乙個值為v的元素。輸入格式為1v

2、向s裡面刪除乙個值為v的元素。輸入格式為2v

3、詢問s裡面的元素兩兩之差絕對值之和。輸入格式為3

對於樣例,

操作3,|1-2|+|1-3|+|2-3|=4

操作1 4之後,集合中的數字為1 2 3 4

操作3,|1-2|+|1-3|+|2-3|+|1-4|+|2-4|+|3-4|=10

操作2 2之後,集合中的數字為1 3 4

操作3,|1-3|+|1-4|+|3-4|=6

input

第一行輸入兩個整數n,q表示集合中初始元素個數和操作次數。(1<=n,q<=100,000)

第二行給出n個整數a[0],a[1],a[2],…,a[n-1],表示初始集合中的元素。(0<=a[i]<=1,000,000,000) 

接下來q行,每行乙個操作。(0<=v<=1,000,000,000)

output

對於第2類操作,如果集合中不存在值為v的元素可供刪除,輸出-1。

對於第3類操作,輸出答案。

input示例

3 5

1 2 3

31 4

32 2

3

output示例

4106

吐槽: 心累啊,這題活生生我交了55發才過,一直卡在第10組和15組之間,不是第10組超時,就是第15組超時,試了一大波姿勢,才勉強過了全部資料,唉! 還是太弱了.

題解: 我是用分塊來解決這道題目的.首先把n個數分成sqrt(n) 個塊,然後乙個塊乙個塊的處理,具體怎麼處理,我就不說了,自己想想應該可以明白.

不過如果這樣做的話,是會超時的,你還需要考慮在某些情況下,重新分塊,因為題目有刪除和插入操作,可能會使某個塊數太多,或者還少,這都會影響效率.

最後卡著時限過,這題如果放在區域賽來搞,估計我會瘋掉~~

ac**:#include #include #include #include #include using namespace std;

const int n = 1e6 + 10;

typedef long long ll;

multisetsb[10000];

ll sum[10000],res,nres;

int a[n],n,m;

bool flag;

inline void in(int &x)

}inline void pt(ll x)

ll add(int v,int n)

if(*sb[i].rbegin() >= v)

ans += sum[i];

num += sb[i].size();

}if(cnt > 500 || sb[id].size() > 5000) flag = true;

if(sb[id].size() && *sb[id].rbegin() >= v)

for(auto it: sb[id])

for(int i = id + 1; i < n; i++)

if(*sb[i].begin() == v)

for(auto it: sb[i])

else break;

}tp = res - ans - tp;

ntp = nres - num - ntp;

ans = num * v - ans + tp - ntp * v;

sb[id].insert(v);

nres++;

res += v;

sum[id] += v;

return ans;

}ll sub(int v,int n)

if(*sb[i].rbegin() >= v)

ans += sum[i];

num += sb[i].size();

}if(sb[id].find(v) == sb[id].end()) return -1;

if(cnt > 500 || sb[id].size() > 50000) flag = true;

for(auto it: sb[id])

for(int i = id + 1; i < n; i++)

if(*sb[i].begin() == v)

for(auto it: sb[i])

else break;

}tp = res - ans - tp;

ntp = nres - num - ntp;

ans = num * v - ans + tp - ntp * v;

sb[id].erase(sb[id].find(v));

nres--;

res -= v;

sum[id] -= v;

return ans;

}int build(int n,ll &ans)

}n = pos;

int unit = (int)sqrt(n + 0.5);

nres = pos;

pos = res = 0;

for(int i = 0,t = 0; i < n; i++)

t++;

sb[pos].insert(a[i]);

sum[pos] += a[i];

ans += 1ll * a[i] * i - res;

res += a[i];

}pos++;

return pos;

}void work()

t++;

sb[pos].insert(a[i]);

sum[pos] += a[i];

ans += 1ll * a[i] * i - res;

res += a[i];

}pos++;

int q = m;

unit = sqrt(m + 0.5) * 2;

while(m--) else else

ans += add(v,pos);

} else

}if(flag) pos = build(pos,ans);

}}int main()

演算法馬拉松24

n 1個點的多邊形。給外圈的邊標記上1 n,裡圈的邊也標記上1 n,使得對於乙個外圈相鄰點與中間點構成的三角形的邊權之和都相等。n le 10 6 顯然每個三角形權值和為 frac 一開始簡化成n個數排乙個環,相鄰兩個數的和不相等並且有上下界,然後並不好做 構造了一下n 5發現外圈正好1.5,內圈1...

演算法馬拉松14 棋盤問題

上帝創造了乙個n m棋盤,每乙個格仔都只有可能是黑色或者白色的。亞當和夏娃在玩乙個遊戲,每次尋找邊長為x的正方形,其中每個格仔必須為黑色,然後將這些格仔染白。如果誰不能操作了,那麼那個人就輸了。亞當喜歡質數。夏娃喜歡1,但討厭2。因此他們規定,x只有可能是非2質數或者是1。現在他們想知道,如果他們都...

演算法馬拉松14 棋盤問題

棋盤問題 system message 命題人 基準時間限制 1 秒 空間限制 131072 kb 分值 40 上帝創造了乙個n m棋盤,每乙個格仔都只有可能是黑色或者白色的。亞當和夏娃在玩乙個遊戲,每次尋找邊長為x的正方形,其中每個格仔必須為黑色,然後將這些格仔染白。如果誰不能操作了,那麼那個人就...