cube.js 最近的一些新功能
阿新 • • 發佈:2020-11-04
傳送門
不得不說,NOI Online的質量確實不錯,有一定的思維難度,而且比較新穎。
怎麼說呢,這題我差點就搞出來了。
這題剛開始我一點思路都沒有,後來經過大量的手模後發現了一些規律,知道這個規律後,題目的一大半就解決了。
記在前\(i\)個數中,比\(a_i\)大的數的個數為\(b_i\),那麼每一輪氣泡排序後,所有\(b_i\)都會-1,直到\(b_i\)等於0.
說白了,就是讓求
這個結論的證明,可以這麼想:如果在\(a_i\)前面有比\(a_i\)大的,那麼這其中最大的數一定會在氣泡排序中和\(a_i\)交換,那麼\(b_i\)
那這東西怎麼求呢?我就卡在了這裡,氣死了。
其實我們只要維護一個權值線段樹(樹狀陣列),每一次求大於\(x\)的\(b_i\)個數及其值的和就行了……
結果我維護了一個序列線段樹,然後用最大最小值一頓亂搞剪枝,拿了60分……唉。
詢問到這就完事了,至於修改,也很簡單。
因為只是相鄰的兩個數交換,所以隻影響\(b_i\)和\(b_{i+1}\)。
如果\(a_i < a_{i+1}\),那麼\(b'_i = b_{i+1}, b'_{i+1} = b_i+1\)。
如果\(a_i > a_{i+1}\)
在樹狀陣列上單點修改即可。
上程式碼:
#include<cstdio> #include<iostream> #include<cmath> #include<algorithm> #include<cstring> #include<cstdlib> #include<cctype> #include<vector> #include<queue> #include<assert.h> #include<ctime> using namespace std; #define enter puts("") #define space putchar(' ') #define Mem(a, x) memset(a, x, sizeof(a)) #define In inline #define forE(i, x, y) for(int i = head[x], y; ~i && (y = e[i].to); i = e[i].nxt) typedef long long ll; typedef double db; const int INF = 0x3f3f3f3f; const db eps = 1e-8; const int maxn = 2e5 + 5; In ll read() { ll ans = 0; char ch = getchar(), las = ' '; while(!isdigit(ch)) las = ch, ch = getchar(); while(isdigit(ch)) ans = (ans << 1) + (ans << 3) + ch - '0', ch = getchar(); if(las == '-') ans = -ans; return ans; } In void write(ll x) { if(x < 0) x = -x, putchar('-'); if(x >= 10) write(x / 10); putchar(x % 10 + '0'); } In void MYFILE() { #ifndef mrclr freopen("ha2.in", "r", stdin); freopen("ha.out", "w", stdout); #endif } int n, m, a[maxn], b[maxn]; int c[maxn]; In int lowbit(int x) {return x & -x;} In void A(int x) { for(; x <= n; x += lowbit(x)) c[x]++; } In int Q(int x) { int ret = 0; for(; x; x -= lowbit(x)) ret += c[x]; return ret; } ll c2[maxn], cnum[maxn]; In void update(int x, int d) { ll tp = x; for(int i = n - x + 1; i <= n + 1; i += lowbit(i)) c2[i] += tp * d, cnum[i] += d; } In ll query(int x) { if(x >= n) return 0; ll sum = 0, num = 0; for(int i = n - x + 1; i; i -= lowbit(i)) sum += c2[i], num += cnum[i]; return sum - num * x; } int main() { // MYFILE(); n = read(), m = read(); for(int i = 1; i <= n; ++i) a[i] = read(); for(int i = 1; i <= n; ++i) { b[i] = Q(n - a[i] + 1); A(n - a[i] + 1); } for(int i = 1; i <= n; ++i) update(b[i], 1); for(int i = 1; i <= m; ++i) { int op = read(), x = read(); if(op == 1) { int tp1 = b[x], tp2 = b[x + 1]; if(a[x] < a[x + 1]) { b[x] = tp2, b[x + 1] = tp1 + 1; update(tp1, -1), update(tp1 + 1, 1); } else { b[x] = tp2 - 1, b[x + 1] = tp1; update(tp2, -1), update(tp2 - 1, 1); } swap(a[x], a[x + 1]); } else write(query(x)), enter; } return 0; }