看給出的部分分,給出的縱座標都相同
於是從所有魚頭胖往每個牆的兩個端點分別引一條線
覆蓋到胖頭魚所在的縱座標線,可以差分以下,左邊的線 \(-1\) 右邊的 \(+1\)
可能會有重複覆蓋的情況
於是可以用類似括號匹配的方法對每個魚頭胖引出的線進行處理
可以擴充套件這個做法,只需要將所有線都存到牆的端點裡,再按照極角序排序
然後再跟胖頭魚的連線比較二分一下,就能知道要減或者加多少個 \(1\) 了
可以用叉積來進行極角序排序
code
#include//#define int long long//overflow !!! memory limit !!!
#define rint signed
#define inf 0x3f3f3f3f3f3f3f3f
using namespace std;
inline int read()
while(ch>='0'&&ch<='9')
return x*f;
}int n,k,m,op;
int x[100010],y[100010];
int l[60],r[60],h[60];
struct data};
struct dddd};
vectorvec[110];
vectorv;
signed main());
v.emplace_back((dddd));
} sort(v.begin(),v.end());
for(int j=0,l=0,r=0,k=0;j
正著新增乙個數,修改的位置均攤 \(o(n)\) 個,可以根據這個做,我不太會
於是考慮倒著刪除乙個數
那修改的區間肯定是他上一次出現的位置一直往前直到 \(mex = a_i\)
可以用線段樹上二分找到這個位置
那現在就要維護區間賦值和區間歷史值和
線段樹上每個節點維護兩個資訊,乙個是當前的 \(mex\) 乙個是 \(sum\)
\(sum\) 表示的就是以當前位置為左端點,右端點在現在列舉的位置到 \(n\) 的區間的 \(mex\) 值和
用類似掃瞄線的思路把詢問離線下來
拆成 \(l\) 和 \(r+1\) 分別詢問 \([l,r]\) 的值然後造成 \(+1,-1\) 的貢獻
具體維護,我用了 \(3\) 個標記
分別是 \(c,u,v\) 分別表示累加次數,賦值標記,在賦值標記後的累加貢獻
下傳時先 \(c\) 再 \(u\) , \(v\) 無所謂
下傳 \(c\) 時要先判斷左右兒子有沒有 \(u\) ,有的話就轉成 \(v\) 沒有就正常下傳
code#include#define int long long//overflow !!! memory limit !!!
#define rint signed
#define lson rt<<1
#define rson rt<<1|1
#define inf 0x3f3f3f3f3f3f3f3f
using namespace std;
inline int read()
while(ch>='0'&&ch<='9')
return x*f;
}int n,q,blo;
int a[1000010],pre[1000010],lst[1000010];
bool vis[1000010];
int ans[1000010],mex[1000010];
int bl[1000010],v[1000010];
int l[1010],r[1010];
int sum[1010],vsum[1010],utag[1010],ctag[1010],vtag[1010],mx[1010];
struct data;
vectorvec[1000010];
struct segst[1000010*4];
inline void pushup(int rt)
inline void pushdown(int rt,int l,int r)
if(st[rt].utag!=-1)
if(st[rt].vtag)
}void build(int rt,int l,int r)
void upd(int rt,int l,int r,int l,int r,int k)
int query(int rt,int l,int r,int l,int r)
int getpos(int rt,int l,int r,int k)
signed main()
for(int i=n,v=0;i;i--)
build(1,1,n);q=read();
for(int i=1,l,r;i<=q;i++));
vec[r+1].emplace_back((data));
} for(int i=n,l,r;i;i--)
if(st[1].utag!=-1) st[1].vtag+=st[1].utag,st[1].vsum+=st[1].utag*n;
else st[1].ctag++,st[1].vsum+=st[1].sum;
} for(int i=1;i<=q;i++) printf("%lld\n",ans[i]);
return 0;
}
轉化一下,就是求本質不同子串個數,一般用 \(sa\) 或者 \(sam\)
由於最小表示法,所以用 \(sa\) 來求
比較時,先二分求出 \(lcp\) 再比較下一位的值
將字串的雜湊定義為每個字元與他前乙個相同的字元相差的距離
用主席樹存下每乙個字尾的雜湊值
排完序後直接求本質不同子串個數
code#include//#define int long long//overflow !!! memory limit !!!
#define rint signed
#define cmin(x,y) ((x)<(y))?(x):(y)
#define uint unsigned long long
#define inf 0x3f3f3f3f3f3f3f3f
using namespace std;
inline int read()
while(ch>='0'&&ch<='9')
return x*f;
}int n,ans;
int a[50010],t[50010];
int rt[50010],lst[50010],tot;
int pre[50010],nxt[50010],v[50010];
uint pw[50010];
struct segst[50010*20];
inline void pushup(int x,int l,int r)
void build(int &x,int l,int r)
void upd(int &x,int l,int r,int pos,uint k)
uint query(int x,int l,int r,int l,int r)
inline int getlcp(int x,int y)
return res;
}inline int s(int x,int k)
inline bool cmp(int x,int y)
if(res==min(lenx,leny)) return lenx
省選模擬 19 09 11
ps.博主趁資訊課摸魚考的暴零模擬 看門人憑感覺就知道是長鏈剖分,將路徑查分一下,dis u di sv 2 dis lc adis u dis v 2 dis disu disv 2 disl ca 維護fu,if fu,i 表示u的子樹,深度為 i 的點的 dis disdi s最大值 考慮如何...
省選模擬96
容易發現當 k 3 時無解。然後容易證明當 k 3 時,只有 m 3 才是有解的。然後直接做不好做,考慮欽定然後容斥出合法方案。對於 k 3 列舉乙個點,然後計算另乙個的方案數。其他情況類似,欽定滿足條件的角,然後容斥。然後對於每乙個 o n 的式子用組合恒等式大力化簡就可以做到 o 1 了。考慮每...
省選模擬86
首先考慮基礎的dp定義,那麼發現轉移需要的係數只和dp是奇數的點的個數有關,所以將這個東西記錄在dp狀態中就行了。然後推一下dp轉移,發現轉移係數和奇數的點的個數沒有關係,只與是否存在這樣的點有關,所以用01來記錄就可以了。考慮用總方案減去不合法的方案,也就是1號點能到達的點和2號點能到達的點沒有交...