毕生所学(基础)
liuchijun
·
·
算法·理论
毕生所学,缺点请补充\
$update12.07$补充离散化\
$update01.20$补充tarjan\
$update02.22$补充ST表\
$update03.29$补充AC机\
$update26.1.30$改善tarjan,补充线性筛素数,线性求积性函数
```cpp
//快速幂
long long qpow(int x,int n)
{
long long res = 1;
while(n)
{
if(n & 1)
res = 1ll * x * x % mod;
x = 1ll * x * x % mod;
n >>= 1;
}
return res;
}
//二分
int search(int l,int r,int x)
{
int mid,res = -1;
while(l <= r)
{
mid = (l + r) / 2;//l+(r-l)>>1
if(a[mid] >= x)
res = mid,
r = mid - 1;
else
l = mid + 1;
}
return res;
}
//建树并且中序遍历
const int N = 1010;
struct binarytree{
int val,lc,rc;
}tree[N];
void inorder(int node)//lc -> rt -> rc
{
if(node == 0)
return;
inorder(tree[node].lc);
cout << node.val << ' ';
inorder(tree[node].rc);
}
//dfs
void dfs(int u,int fa)
{
dep[u] = 1;
for(auto ed : G[u])
{
int v = ed.v;
if(v == fa)
continue;
dep[v] = dep[u] + 1;
dfs(v,u);
}
}
//bfs
vis[s]=true;
queue<int>q;
q.push(s);
while(!q.empty()){
int u=q.front();
cout<<u<<' ';
q.pop();
for(int i=head[u];i;i=e[i].next){
int v=e[i].v;
if(vis[v])
continue;
vis[v]=true;
q.push(v);
}
}
//floodfill
const int dx[4]={-1,0,0,1};
const int dy[4]={0,-1,1,0};
void dfs(int x,int y,int newcolor int oldcolor){
c[x][y]=newcolor;
for(int i=0;i<4;++i){
int nx=x+dx[i],ny=y+dy[i];
if(nx<1||nx>n||ny<1||ny>n)
continue;
if(c[nx][ny]!=oldcolor)
continue;
dfs(nx,ny,newcolor,oldcolor);
}
}
//前缀和求区间和
for(ll i=1;i<=n;i++)
cin>>a[i],s[i]=s[i-1]+a[i];
cin>>m;
for(ll i=1;i<=m;i++)
cin>>l>>r,cout<<s[r]-s[l-1]<<endl;
//树状数组及加、求和操作
struct node{
int l,r,sum;
}t[2000010];
void build(int p,int l,int r)
{
t[p].l=l;t[p].r=r;t[p].sum=a[l];
int m=(l+r)>>1;
if(l==r)
{
return;
}
else
{
build(p*2,l,m);
build(p*2+1,m+1,r);
t[p].sum=t[p*2].sum+t[p*2+1].sum;
}
}
void update(int p,int x,int k)
{
if(x<t[p].l||x>t[p].r)return;
t[p].sum+=k;
if(t[p].l==t[p].r)return ;
update(p*2,x,k);
update(p*2+1,x,k);
}
int query(int p,int x,int y)
{
if(x>t[p].r||t[p].l>y)return 0;
if(x<=t[p].l&&t[p].r<=y)return t[p].sum;
return query(p*2,x,y)+query(p*2+1,x,y);
}
//求逆序对
void msort(int b,int e)
{
if(b==e)
return;
int mid=(b+e)/2,i=b,j=mid+1,k=b;
msort(b,mid),msort(mid+1,e);
while(i<=mid&&j<=e)
if(a[i]<=a[j])
c[k++]=a[i++];
else
c[k++]=a[j++],ans+=mid-i+1;
while(i<=mid)
c[k++]=a[i++];
while(j<=e)
c[k++]=a[j++];
for(int l=b;l<=e;l++)
a[l]=c[l];
}
//迪杰斯特拉算法
struct edge{
int v,w;
};
struct node{
int dis,u;
bool operator >(const node& a)const{
return dis>a.dis;
}
};
vector<edge>e[N];
int dis[N],vis[N];
priority_queue<node,vector<node>,greater<node>>q;
void dijkstra(int s){
memset(dis,0x3f,sizeof(dis));
dis[s]=0;
q.push({0,s});
while(!q.empty()){
int u=q.top().u;
q.pop();
if(vis[u])continue;
vis[u]=1;
for(auto ed:e[u]){
int w=ed.w,v=ed.v;
if(dis[v]>dis[u]+w){
dis[v]=dis[u]+w;
q.push({dis[v],v});
}
}
}
}
//普利姆算法
struct e{
ll v,w,x;
}e[M*2];
ll n,m,h[N],cnte;
void addedge(ll u,ll v,ll w)
{e[++cnte]={v,w,h[u]},h[u]=cnte;}
struct s{
ll u,d;
};
bool operator<(const s&x,const s&y){return x.d>y.d;}
priority_queue<s>q;
ll dis[N];
bool vis[N];
ll res=0,cnt=0;
void prim(){
memset(dis,0x3f,sizeof(dis));
dis[1]=0;
q.push({1,0});
while(!q.empty()){
if(cnt>=n)
break;
ll u=q.top().u,d=q.top().d;
q.pop();
if(vis[u])continue;
vis[u]=true;
++cnt;
res+=d;
for(ll i=h[u];i;i=e[i].x){
ll v=e[i].v,w=e[i].w;
if(w<dis[v]){
dis[v]=w,q.push({v,w});
}
}
}
}
//链式前向星
struct node{
ll to;
ll w;
ll nxt;
}e[maxn];
ll head[maxn],cnt;
void addedge(ll u,ll v,ll w){
e[cnt].to=v;
e[cnt].w=w;
e[cnt].nxt=head[u];
head[u]=cnt++;
}
void visit(ll u){
for(ll i=head[u];i;i=e[i].nxt){
int v=e[i].v;
int w=e[i].w;
}
}
//离散化 int arr[n+1]
for(int i=1;i<=n;i++)//step1
tmp[i]=arr[i];
sort(tmp+1,tmp+n+1);//step2
//int len=unique(tmp+1,tmp+n+1)-(tmp+1);//step3
ll quchong(ll* arr,ll n)//等价于unique step3
{
int k=1;
for (int i=2;i<=n;i++)
if (arr[i]!=q[k]) arr[++k]=q[i];
return k;
}
//for(int i=1;i<=n;i++)
// arr[i]=lower_bound(tmp+1,tmp+len+1,arr[i])-tmp;//step4
ll binary_search(ll l,ll r,ll x)//binarysearch step4
{
ll m;
while (l<=r)
{
m=l+r>>1;
if (b[m]==x) return m;
if (b[m]<x) l=m+1;
if (b[m]>x) r=m-1;
}
}
//离散化 vector<int>arr
vector<int>tmp(arr);//step1
sort(tmp.begin(),tmp.end());//step2
tmp.erase(unique(tmp.begin(),tmp.end()),tmp.end());//step3
for(int i=0;i<n;i++)
arr[i]=lower_bound(tmp.begin(),tmp.end(),arr[i])-tmp.begin();//step4
//tarjan
class graph{
private :
vector <vector <int> > G,ans;
vector <int> low,dfn,id,ind;
vector <bool> instk;
stack <int> stk;
int t = 0,cnt = 0,n;
public :
graph(int n) : n(n),G(n + 1),low(n + 1,-1),dfn(n + 1,-1),id(n + 1,-1),ind(n + 1,0),instk(n + 1,false){};
void addedge(int u,int v)
{
G[u].push_back(v);
}
void tarjan(int u)
{
dfn[u] = low[u] = ++t;
stk.push(u);
instk[u] = true;
for(int v : G[u])
{
if(dfn[v] == -1)
{
tarjan(v);
low[u] = min(low[u],low[v]);
}
else
if(instk[v])
low[u] = min(low[u],dfn[v]);
}
if(low[u] == dfn[u])
{
int node;
do
{
node = stk.top();
stk.pop();
instk[node] = false;
id[node] = cnt;
}while(node != u);
cnt++;
}
}
void visit()
{
for(int i = 1;i <= n;i++)
if(dfn[i] == -1)
tarjan(i);
}
void build()
{
ans.resize(cnt);
for(int u = 1;u <= n;u++)
for(int v : G[u])
if(id[u] != id[v])
ans[id[u]].push_back(id[v]);
for(int i = 0;i < cnt;i++)
sort(ans[i].begin(),ans[i].end()),
ans[i].erase(unique(ans[i].begin(),ans[i].end()),ans[i].end());
for(int i = 0;i < cnt;i++)
for(int v : ans[i])
ind[v]++;
}
vector <int> topo()
{
vector <int> res;
queue <int> q;
for(int i = 0;i < cnt;i++)
if(ind[i] == 0)
q.push(i);
while(!q.empty())
{
int u = q.front();
q.pop();
res.push_back(u);
for(int v : ans[u])
{
ind[v]--;
if(ind[v] == 0)
q.push(v);
}
}
return res;
}
};
//ST表
int n,m;
int st[100010][20];
int main()
{
scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++)
{
int x;
scanf("%d",&x);
st[i][0]=x;
}
int lg=(int)log2(n);
for(int j=1;j<=lg;j++)
for(int i=1;i<=n-(1<<j)+1;i++)
st[i][j]=max(st[i][j-1],st[i+(1<<(j-1))][j-1]);
for(int i=1;i<=m;i++)
{
int l,r;
scanf("%d%d",&l,&r);
lg=(int)log2(r-l+1);
printf("%d\n"max(st[l][lg],st[r-(1<<lg)+1][lg]));
}
return 0;
}
//AC机
const int maxn = 2e5 + 5;
const int len = 2e6 + 5;
const int size = 2e5 + 6;
int n;
struct node{
int son[27];
int ans,fail,degree,idx;
void init()
{
memset(son,0,sizeof(son));
ans = fail = idx = 0;
}
}trie[size];
int ans[maxn];
int tot,pidx;
void init()
{
tot = pidx = 0;
trie[0].init();
}
void insert(char s[],int &idx)
{
int u = 0;
for(int i = 1;s[i];i++)
{
int &son = trie[u].son[s[i] - 'a'];
if(!son)
son = ++tot,
trie[son].init();
u = son;
}
if(!trie[u].idx)
trie[u].idx = ++pidx;
idx = trie[u].idx;
}
void build()
{
queue <int> q;
for(int i = 0;i < 26;i++)
if(trie[0].son[i])
q.push(trie[0].son[i]);
while(!q.empty())
{
int u = q.front();
q.pop();
for(int i = 0;i < 26;i++)
{
if(trie[u].son[i])
{
trie[trie[u].son[i]].fail = trie[trie[u].fail].son[i];
trie[trie[trie[u].fail].son[i]].degree++;
q.push(trie[u].son[i]);
}
else
trie[u].son[i] = trie[trie[u].fail].son[i];
}
}
}
void query(char t[])
{
int u = 0;
for(int i = 1;t[i];i++)
u = trie[u].son[t[i] - 'a'],
trie[u].ans++;
}
void topo()
{
queue <int> q;
for(int i = 0;i <= tot;i++)
if(trie[i].degree == 0)
q.push(i);
while(!q.empty())
{
int u = q.front();
q.pop();
ans[trie[u].idx] = trie[u].ans;
int v = trie[u].fail;
trie[v].ans += trie[u].ans;
if(! --trie[v].degree)
q.push(v);
}
}
char s[len];
int idx[maxn];
int main()
{
init();
scanf("%d",&n);
for(int i = 1;i <= n;i++)
{
scanf("%s",s + 1);
insert(s,idx[i]);
ans[i] = 0;
}
build();
scanf("%s",s + 1);
query(s);
topo();
for(int i = 1;i <= n;i++)
printf("%d\n",ans[idx[i]]);
return 0;
}
//线性筛素数
void pre(int n)
{
for(int i = 2;i <= n;i++)
{
if(!np[i])
p.push_back(i);
for(int j : p)
{
if(i * j > n)
break;
np[i * j] = true;
if((i % j) == 0)
break;
}
}
}
//线性求积性函数
vector<int> pri;
bool not_prime[N];
int d[N], num[N];
//(d(n) n因子个数)
void pre(int n)
{
d[1] = 1;
for(int i = 2;i <= n;++i)
{
if (!not_prime[i])
{
pri.push_back(i);
d[i] = 2; // 1, i
num[i] = 1; // i = i ^ 1 num[i*i]=2 num[16]=4 num[28]=2 num[30]=1
}
for(int pri_j : pri)
{
if (i * pri_j > n)
break;
not_prime[i * pri_j] = true;
if (i % pri_j == 0)
{
num[i * pri_j] = num[i] + 1; // gcd(i, pri_j) == pri_j
d[i * pri_j] = d[i] / num[i * pri_j] * (num[i * pri_j] + 1);
// a = i * pri_j
// d[n] = d[prij^num[a]] * d[b]
// d[n] = (num[a] + 1) * d[b] 1
// d[n/prij] = num[a] * d[b] 2
// 1式 除以 2式
// d[n] = d[n/prij] * (num[a] + 1) / num[a]
break;
}
num[i * pri_j] = 1;
d[i * pri_j] = d[i] * 2; // d[pri_j]
}
}
}
```