差和問題
有乙個集合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)output第二行給出n個整數a[0],a[1],a[2],…,a[n-1],表示初始集合中的元素。(0<=a[i]<=1,000,000,000)
接下來q行,每行乙個操作。(0<=v<=1,000,000,000)
對於第2類操作,如果集合中不存在值為v的元素可供刪除,輸出-1。input示例對於第3類操作,輸出答案。
3 5output示例1 2 3
31 4
32 2
3
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的正方形,其中每個格仔必須為黑色,然後將這些格仔染白。如果誰不能操作了,那麼那個人就...