『P1177』與『P2572』聯合題解
阿新 • • 發佈:2021-09-28
P1177
基數排序
基本理論就是把一個數字分成k個關鍵字,每次對n個數同時對於k關鍵字排序
時間複雜度\(O(n \times \frac{n_max}{radix})\),空間複雜度是\(O(n+radix)\)
radix為取的基數,通常取 \(65536\) 或者是 \(256\),
\(NOI\) 和 \(NOIp\) 的配置大概取 \(256\) 為基數能卡進 \(L1\) 快取記憶體,但是你取 \(65536\) 在聯賽裡就卡不進 \(L1\) 記憶體訪問不連續就會非常慢……(但是luogu評測姬 \(L1\) 似乎大得離譜
#include <bits/stdc++.h> using namespace std; #define INF 1<<30 #define int long long #define pb push_back %:define ill unsigned long long %:define lowbit(x) (x&(-x)) %:define Int unsigned int #define pii pair<int,int> template<typename _T> inline void read(_T &x) { x = 0;int f= 1;char s = getchar(); while(s<'0'||s>'9'){f=1;if(s=='-')f=-1;s=getchar();} while('0'<=s&&s<='9'){x=(x<<3)+(x<<1)+s-'0';s=getchar();} x*=f; } const int U = 256; const int BIT = 8; const int np = 1e5 + 5; int n; int a[np]; int b[np]; int bac[np]; inline int Get(int x,int d) { return (x >> BIT * d) & (U - 1); } inline void sort_() { for(int d=0;d<4;d++) { for(int i=0;i<U;i++) bac[i] = 0; for(int i=1;i<=n;i++) bac[Get(a[i],d)]++; for(int i=0;i<U;i++) bac[i] += bac[i-1]; for(int i=n;i>=1;i--) b[bac[Get(a[i],d)]--] = a[i]; for(int i=1;i<=n;i++) a[i] = b[i]; } } signed main() { read(n); for(int i=1;i<=n;i++) read(a[i]); sort_(); for(int i=1;i<=n;i++) cout<<a[i]<<" "; }
P2572
裸的資料結構題,題目已經明示線段樹維護。
(一開始我還想敲一個珂朵莉苟過去,但直接被卡成\(30pts\)
難點在於懶標記的維護與下放,對於懶標記問題
思考問題的時候需要牢牢把握一下幾點:
懶標記本質是對自己兒子修改的訊號
需要思考懶標記之間的優先順序關係
需要思考下放懶標記時對子節點懶標記的影響
這樣來思考問題解決懶標記還是蠻輕鬆的
(把這篇整上來只是想記錄一下這種方法,而不是就題論題
#include <bits/stdc++.h> using namespace std; #define INF 1<<30 #define int long long #define pb push_back %:define ill unsigned long long %:define lowbit(x) (x&(-x)) %:define Int unsigned int template<typename _T> inline void read(_T &x) { x = 0;int f= 1;char s = getchar(); while(s<'0'||s>'9'){f=1;if(s=='-')f=-1;s=getchar();} while('0'<=s&&s<='9'){x=(x<<3)+(x<<1)+s-'0';s=getchar();} x*=f; } const int np = 1e5 + 5; struct node{ int l,r; int sum; int lmax[2],rmax[2],maxn_len[2]; int cov[2]; int typ_f; node *ls,*rs; inline bool inrange(int L,int R){return L<=l&&r<=R;} inline bool outofrange(int L,int R){return r < L||R < l;} inline void pushup() { sum = ls->sum + rs->sum; for(int i=0;i<=1;i++) { maxn_len[i] = ls->rmax[i] + rs->lmax[i]; maxn_len[i] = max(maxn_len[i] , ls->maxn_len[i]); maxn_len[i] = max(maxn_len[i] , rs->maxn_len[i]); if(ls->lmax[i] == ls->r - ls->l + 1 )lmax[i] = ls->lmax[i] + rs->lmax[i]; else lmax[i] = ls->lmax[i]; if(rs->rmax[i] == rs->r - rs->l + 1)rmax[i] = rs->rmax[i] + ls->rmax[i]; else rmax[i] = rs->rmax[i]; } } inline void pushdown() { if(cov[1]) { ls->maketag(1); rs->maketag(1); cov[1] = 0; } if(cov[0]) { ls->maketag(0); rs->maketag(0); cov[0] = 0; } if(typ_f) ls->make_f() , rs->make_f(),typ_f^=1; } inline void make_f() { sum = (r - l + 1) - sum; swap(lmax[1],lmax[0]); swap(rmax[1],rmax[0]); swap(maxn_len[1],maxn_len[0]); typ_f ^= 1; } inline void maketag(int vl) { sum = (r - l + 1) * vl; lmax[vl] = r - l + 1 , lmax[!vl] = 0; rmax[vl] = r - l + 1 , rmax[!vl] = 0; maxn_len[vl] = r-l + 1,maxn_len[!vl] = 0; cov[vl] = 1;cov[!vl] = typ_f = 0; } inline int query_opt_3(int L,int R) { if(inrange(L,R)) { return sum; } else { if(!outofrange(L,R)) { pushdown(); return ls->query_opt_3(L,R) + rs->query_opt_3(L,R); } else return 0; } } inline int query_opt_4(int L,int R) { if(inrange(L,R)) { return maxn_len[1]; } else { if(!outofrange(L,R)) { pushdown(); int mid = l + r >> 1; int x = 0; if( L<= mid && mid<=R && L<=mid + 1 && mid + 1<=R && ls->rmax[1] && rs->lmax[1]) { if(mid + rs->lmax[1] <= R) x+= rs->lmax[1]; else x += R-(mid + 1) + 1; if(L <= mid - ls->rmax[1] + 1) x += ls->rmax[1]; else x += mid - L + 1; } return max({x ,ls->query_opt_4(L,R) , rs->query_opt_4(L,R) }); } else return 0; } } inline void cover(int L,int R,int vl) { if(inrange(L,R)) { maketag(vl); return ; } else { if(!outofrange(L,R)) { pushdown(); ls->cover(L,R,vl); rs->cover(L,R,vl); pushup(); } } } inline void qf(int L,int R) { if(inrange(L,R)) { make_f(); return; } else { if(!outofrange(L,R)) { pushdown(); ls->qf(L,R); rs->qf(L,R); pushup(); } } } }mem[np * 2 + 10] , *pool = mem; int a[np]; inline node *New(){return ++pool;} inline node *build(int L,int R) { node *u = New(); u->l = L; u->r = R; if(L == R) { u->ls = u->rs = NULL; if(a[L]) u->sum = u->maxn_len[1] = u->lmax[1] = u->rmax[1] = 1; else u->maxn_len[0] = u->lmax[0] = u->rmax[0] = 1; } else { int mid = L+R>>1; u->ls = build(L,mid); u->rs = build(mid + 1,R); u->pushup(); } return u; } node *rot; signed main() { int n,m; read(n); read(m); for(int i=1;i<=n;i++) read(a[i]); rot = build(1,n); for(int i=1,opt,l,r;i<=m;i++) { read(opt); read(l); read(r); l++; r++; switch(opt) { case 0:{ rot->cover(l,r,0); break; } case 1:{ rot->cover(l,r,1); break; } case 2:{ rot->qf(l,r); break; } case 3:{ cout<<rot->query_opt_3(l,r)<<'\n'; break; } case 4:{ cout<<rot->query_opt_4(l,r)<<'\n'; break; } } } return 0; }
至於為什麼是聯合題解
誒
因為兩個題的字數加起來不是很多,分開寫有點浪費而已