CSP/NOIP 之前還需要學/複習的東西
阿新 • • 發佈:2021-06-18
主要是複習。
當然可能能會發現自己之前學假瞭然後重學的。
圖論類
- 割點
void tarjan(int u,int fa){ vis[u]=1;int chi=0;//統計孩子數量 dfn[u]=low[u]=++cnt; for(int i=head[u];i;i=e[i].nxt){ int to=e[i].to; if(!vis[to]){ chi++;tarjan(to,u); low[u]=min(low[to],low[u]); if(fa!=u&&low[to]>=dfn[u]&&!flag[u]){//第一個依據 flag[u]=1; res++;//割點數量 } } else if(to!=fa) low[u]=min(low[u],dfn[to]); } if(fa==u&&chi>=2&&!flag[u]){//第二個依據 flag[u]=1;res++; } }
- 橋
void tarjan(int u,int fat){ fa[u]=fat; low[u]=dfn[u]=++cnt; for(int i=head[u];i;i=e[i].nxt){ int v=e[i].to; if(!dfn[v]){ tarjan(v,u);low[u]=min(low[u],low[v]); if(low[v]>dfn[u]){vis[v]=true;++bri;}//bri 是割邊的數量 } else if(dfn[v]<dfn[u]&&v!=fat) low[u]=min(low[u],dfn[v]); } }
資料結構類
- 哈夫曼樹
- 笛卡爾樹
signed main(){ n=read(); for(int i=1,k;i<=n;i++){ a[i]=read();k=top; while(k&&a[zhan[k]]>a[i]) k--; if(k) rs[zhan[k]]=i; if(k<top) ls[i]=zhan[k+1]; zhan[++k]=i;top=k; } for(int i=1;i<=n;i++)ans1^=(i*(ls[i]+1)); for(int i=1;i<=n;i++)ans2^=(i*(rs[i]+1)); printf("%lld %lld\n",ans1,ans2); return 0; }
- 主席樹
//靜態區間第 k 小
#define ls(x) t[x].ls
#define rs(x) t[x].rs
int n,m,all,cnt;
int a[maxn],b[maxn],rt[maxn];
struct node{int siz,ls,rs;}t[maxn];
void insert(int last,int &now,int l,int r,int pos){
if(!now) now=++cnt;
t[now].siz=t[last].siz+1;
if(l==r) return;int mid=l+r>>1;
if(pos<=mid) t[now].rs=t[last].rs,insert(t[last].ls,t[now].ls,l,mid,pos);
else t[now].ls=t[last].ls,insert(t[last].rs,t[now].rs,mid+1,r,pos);
}
int query(int last,int now,int l,int r,int val){
if(l==r) return l;
int lef=t[ls(now)].siz-t[ls(last)].siz;
int mid=l+r>>1;
if(val>lef) return query(t[last].rs,t[now].rs,mid+1,r,val-lef);
else return query(t[last].ls,t[now].ls,l,mid,val);
}
int main(){
n=read();m=read();
for(int i=1;i<=n;i++)b[i]=a[i]=read();
sort(b+1,b+n+1);all=unique(b+1,b+n+1)-b-1;
for(int i=1;i<=n;i++)a[i]=lower_bound(b+1,b+all+1,a[i])-b;
for(int i=1;i<=n;i++) insert(rt[i-1],rt[i],1,all,a[i]);
for(int i=1,fr,to,val;i<=m;i++){
fr=read();to=read();val=read();
printf("%d\n",b[query(rt[fr-1],rt[to],1,all,val)]);
}
return 0;
}
- 各種平衡樹(不在大綱中,但是會了總比不會好)
namespace Treap{
int insert(int x){
val[++all]=x;
dat[all]=rand();
sum[all]=cnt[all]=1;
return all;
}
void pushup(int x){
sum[x]=sum[ch[x][0]]+sum[ch[x][1]]+cnt[x];
}
void build(){
root=insert(-INF);
ch[root][1]=insert(INF);
pushup(root);
}
void rotate(int &x,int son){
int tmp=ch[x][son^1];
ch[x][son^1]=ch[tmp][son];
ch[tmp][son]=x;x=tmp;
pushup(ch[x][son]);
pushup(x);
}
void push(int &x,int v){
if(!x) {x=insert(v);return;}
if(v==val[x]) cnt[x]++;
else{
int son=v<val[x]?0:1;push(ch[x][son],v);
if(dat[x]<dat[ch[x][son]]) rotate(x,son^1);
}
pushup(x);
}
void Remove(int &x,int v){
if(!x) return;
if(v==val[x]){
if(cnt[x]>1) {cnt[x]--,pushup(x);return;}
if(ch[x][0]||ch[x][1]){
if(!ch[x][1]||dat[ch[x][0]]>dat[ch[x][1]])
rotate(x,1),Remove(ch[x][1],v);
else rotate(x,0),Remove(ch[x][0],v);
pushup(x);
}
else x=0;return;
}
v<val[x]?Remove(ch[x][0],v):Remove(ch[x][1],v);
pushup(x);
}
int getrank(int x,int v){
if(!x) return -2;
if(v==val[x]) return sum[ch[x][0]]+1;
if(v<val[x]) return getrank(ch[x][0],v);
return sum[ch[x][0]]+cnt[x]+getrank(ch[x][1],v);
}
int getval(int x,int rank){
if(!x) return INF;
if(rank<=sum[ch[x][0]]) return getval(ch[x][0],rank);
if(rank<=sum[ch[x][0]]+cnt[x]) return val[x];
return getval(ch[x][1],rank-sum[ch[x][0]]-cnt[x]);
}
int getpre(int v){
int now=root,pre;
while(now){
if(val[now]<v) pre=val[now],now=ch[now][1];
else now=ch[now][0];
}
return pre;
}
int getnxt(int v){
int now=root,nxt;
while(now){
if(val[now]>v) nxt=val[now],now=ch[now][0];
else now=ch[now][1];
}
return nxt;
}
}
- ST表
//靜態區間最大值
int n,m,a[maxn],Max[maxn][30],l,r;
int Query(int lef,int rig){
int k=log2(rig-lef+1);
return max(Max[lef][k],Max[rig-(1<<k)+1][k]);
}
int main(){
n=read();m=read();
for(int i=1;i<=n;i++) scanf("%d",&Max[i][0]);
for(int j=1;j<=30;j++)
for(int i=1;i+(1<<j)-1<=n;i++)
Max[i][j]=max(Max[i][j-1],Max[i+(1<<(j-1))][j-1]);
for(int i=1;i<=m;i++){
scanf("%d%d",&l,&r);
printf("%d\n",Query(l,r));
}
return 0;
}
數論類
- BSGS
//a^l % Mod = b 求最小非負整數 l(Mod 是質數)
int BSGS(int a,int b,int Mod,int &ret){
a%=Mod;b%=Mod;
if(!a){if(!b){ret=1;return 1;}else return 0;}
int m=ceil(sqrt(Mod));map<int,int> h;
for(int i=0,tmp=b%Mod;i<=m;i++,tmp=tmp*a%Mod) h[tmp]=i;
a=quickpow(a,m,Mod);
for(int i=1,tmp=a%Mod;i<=m;i++,tmp=tmp*a%Mod)
if(h.count(tmp)){ret=i*m-h[tmp];return 1;}
return 0;
}
- CRT,EXCRT
//CRT
void exgcd(int a,int b,int &x,int &y){
if(b==0){x=1;y=0;return;}
exgcd(b,a%b,x,y);
int z=x;x=y;y=z-y*(a/b);
}
signed main(){
n=read();
for(int i=1;i<=n;i++)
a[i]=read(),b[i]=read(),M*=a[i];
for(int i=1;i<=n;i++){
times[i]=M/a[i];
int x=0;int y=0;
exgcd(times[i],a[i],x,y);
ans+=b[i]*times[i]*(x<0?x+a[i]:x);
}
cout<<ans%M;
return 0;
}
//EXCRT
signed main(){
n=read();
int Ans,M,x,y;
for(rr int i=1;i<=n;i++)
m[i]=read(),a[i]=read();
M=m[1],Ans=a[1];
for(int i=2,A,B,C;i<=n;i++){
A=M,B=m[i],C=(a[i]-Ans%B+B)%B;
int now=exgcd(A,B,x,y),f=B/now;
x=quicktimes(x,C/now,f);
Ans+=x*M;M*=f;Ans=(Ans%M+M)%M;
}
printf("%lld\n",Ans);
}
return 0;
}
- Lucas,EXLucas
下午再填坑。
- 高斯消元
- 各種定理
字串類
- Trie
- AC自動機
- KMP,EXKMP
- 字尾陣列
- Manacher
動態規劃類
- 狀壓、區間、樹形、數位、揹包等,基本都看。
其他的
不知道怎麼分類的知識點。
- 各種排序(基數排序,歸併排序,錦標賽排序等)
- 各種 STL