Wind_Flute -- 暮雨笙箫

Wind_Flute -- 暮雨笙箫

目录

目录

Wind_Flute -- 暮雨笙箫

C++知识:

fuction表达式:

lambda表达式:

stl类:

向量vector:

unique去重

队列、栈、双端队列:

优先队列:

辅助:

结构体自定义排序规则:

回型矩阵:

图的四色定理:

KMP(字符串匹配算法)

最大公约数和快速幂

register int/long long/double

缩点

缩点模板题--p3387 模板 缩点

二分&&三分

        二分

        三分

二分不一定比三分更优(codeforce 964 div4 G2)

米勒-拉宾素性检验(MillerRabbin)--时间复杂度(O(logn))

并查集

DFS求因子--时间复杂度O(n^1/4)

计算n以内的素数个数,时间复杂度(O())->n<=1e12

计算n以内的素数个数,时间复杂度(n^(2/3))-->短了很多有没有!

逆元

费马小定理----针对模数为质数求逆元

扩展欧几里得--针对任意数,但不保证逆元真的存在

线性求逆元 --->O(n)时间复杂度内处理好1~n的逆元(前提是mod 是一个质数)

图的建边

链式前向星建边

邻接表

邻接矩阵

最近公共祖先(LCA)

倍增算法(在线

最短路-迪杰斯特拉

树的直径

差分&&前缀和:

一维差分:

二维差分&&二维前缀和

三维前缀和

RMQ查询区间最值

st表的构建:建表O(nlogn) 查询O (log n)

逆序数模板:

区间合并:

筛因子&&质数筛

筛因子:

质数筛:

树状数组  区间修改 区间查询 建树 n log n 查询 log n

线段树 区间加法 区间查询 建树O(nlog n) 查询 log n

单调队列

字符串哈希


C++知识:

fuction表达式:

function<返回值类型(参数表)>函数名=[&](参数表)->返回值类型{return 返回值;};
///下面是样例
function<int(int, int)> f = [&](int a, int b) -> int {
	return add(a, b);
};

lambda表达式:

auto 函数名=[&](参数表)->返回值类型{函数体};
auto check=[&](int i)->bool{return 1;};
///上面是非递归式写法
auto dfs=[&](auto &dfs,ll n)->int{return 1;};
auto fib = [&](auto & fib, int n)  -> int///当然,只是多了一个引用自身,也就是auto && fib的部分
{
    if(n <= 2) return 1;
    else return fib(fib, n - 1) + fib(fib, n - 2);
};///递归式写法
///调用时,fib(fib,int);

stl类:

向量vector:

查找元素最大值:

	vector<int>vec;
	for(int i=1;i<=1000;i++)
    {
        vec.push_back(i);
    }
    cout<<vec[max_element(vec.begin(),vec.end())-vec.begin()]<<'\n';///查找元素最大值
    cout<<vec[min_element(vec.begin(),vec.end())-vec.begin()]<<'\n';///查找元素最小值
unique去重
vector<int>vec;
sort(vec.begin(), vec.end());
vec.erase(unique(vec.begin(),vec.end().),vec.end());
队列、栈、双端队列:
///int可换成其他类型
queue<int>q;///普通队列,先进先出,q.push(x)进,q.pop()出,通过q.front()/q.back()访问首尾元素
stack<int>st;///栈,先进后出,不能访问栈底元素,但可访问栈顶元素,st.top(),同样是push(x)进,pop()出
deque<int>dq;///双端队列,几个实用函数,dq.push_back(),dq.push_front()
///dq.pop_back(),dq.pop_front()
///dq.front(),dq.back()
优先队列:
    /*
    写法:
    	简写(大顶堆):priority_queue<类型>变量名
    	正式:priority_queue<类型,vector<类型>,(比较函数)>变量名
    */
    priority_queue<int>t;///默认为大顶堆
    priority_queue<int,vector<int>,less<int>>q;///大顶堆,也就是说等价于priority_queue<int>q;
    priority_queue<int,vector<int>,greater<int>>p;///小顶堆

辅助:

结构体自定义排序规则:
struct node
{
    ll l,r;///两个参数l,r
    bool operator<(const node&A)/// bool operator<(const 结构体名 & a)
    {
        if(r==A.r)return l<A.l;  ///当前结构体与结构体变量a的大小判断规则,如果当前结构体小,则返回1
        else return r<A.r;
        ///l,r变量默认为当前结构体的变量,A.r和A.l是将要比较的结构体的变量
    };
};
回型矩阵:
#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll a[10000][10000];
int main()
{
    ll n;
    cin>>n;
    ll sum=1;
    ll cnt=1;
    ll i,j;i=j=1;
    while(cnt<=n*n)
    {
        while(a[i][j]==0&&j<=n)
        {
            a[i][j]=cnt;cnt++;j++;
        }
        j--;i++;
        while(a[i][j]==0&&i<=n)
        {
            a[i][j]=cnt;cnt++;i++;
        }
        i--;j--;
        while(a[i][j]==0&&j>=1)
        {
            a[i][j]=cnt;cnt++;j--;
        }
        j++;i--;
        while(a[i][j]==0&&i>=1)
        {
            a[i][j]=cnt;cnt++;i--;
        }
        i++;j++;
    }
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            cout<<a[i][j]<<' ';
        }cout<<'\n';
    }
}

图的四色定理:

        对于图,对点进行填色,用四种颜色便可以保证边的两点颜色不同。

KMP(字符串匹配算法)

	string s1,s2;
    cin>>s1>>s2;
    s1='.'+s1;s2='.'+s2;
    ll n=s1.size()-1;
    ll m=s2.size()-1;
    ///在一串查找二串
    vector<ll>ne(n+1,0);///原名next数组,但next似乎是什么奇怪的关键字,就不用了
    for(int i=2,j=0;i<=m;i++)///ne[i]数组的构建,ne==next
    {
        while(j&&s2[i]!=s2[j+1])j=ne[j];
        if(s2[i]==s2[j+1])j++;
        ne[i]=j;
    }///预处理二串的ne数组
    for(int i=1,j=0;i<=n;i++)
    {
        while(j&&s1[i]!=s2[j+1])j=ne[j];
        if(s1[i]==s2[j+1])j++;
        if(j==m)
        {
            cout<<i-m+1<<'\n';
            j=ne[j];
        }
    }
    for(int i=1;i<=m;i++)
    {
        cout<<ne[i]<<' ';
    }cout<<'\n';

最大公约数和快速幂

ll gcd(ll a,ll b)///辗转相除法
{
    if(b) while((a%=b)&&(b%=a));
    return a+b;
}//最大公约数函数///其实C++有gcd函数,但好像没这个快,而且这个可以防止b是0的情况。

int stein(int a,int b){
	if(a<b) a^=b,b^=a,a^=b;        //交换,使a为较大数;
	if(b==0)return a;                    //当相减为零,即两数相等时,gcd=a;
	if((!(a&1))&&(!(b&1))) return stein(a>>1,b>>1)<<1;   //s1,注意最后的左移,在递归返回过程中将2因子乘上;
	else if((a&1)&&(!(b&1)))return stein(a,b>>1);            //s2;
	else if((!(a&1))&&(b&1))return stein(a>>1,b);
	else return stein(a-b,b);                                             //s3;
}///解决超大数取模
///欧几里得算法(辗转相除法)在处理较小数字时优势是明显的,但对于大整数时,高精度的整除和取余运算就显得非常复杂,所以Stein算法的优点就在于只需要进行移位(位运算)和减法操作,处理高精度GCD问题时相对简便;
///stein>辗转相除非递归>辗转相除递归。
///最小公倍数=a*b/gcd(a,b);
ll spid(ll a,ll b,ll p)
{
    ll ans=1;
    while(b)
    {
        if(b&1)ans=ans*a%p;
        b>>=1;
        a=a*a%p;
    }
    return ans;
}//快速幂函数

register int/long long/double

        register 可以让变量存储在寄存器内,已得到更高的读取效率(原本是存储在内存)。

缩点

        强连通分量:**在有向图G中,如果两个顶点u,v间有一条从u到v的有向路径,同时还有一条从v到u的有向路径,则称两个顶点强连通。如果有向图G的每两个顶点都强连通,称G是一个强连通图。有向非强连通图的极大强连通子图,称为强连通分量。简单来说,对于某一个强连通分量的点集,任意两点之间可以通过有向边相互到达。

///洛谷 P2002 消息扩散
#include<bits/stdc++.h>
#define endl '\n'
#define ll int
#define int int
#define double long double
#define Int __int128
#define pb push_back
#define eb emplace_back
#define MAX_LOG 21
#define ff first
#define ss second
#define M 5005
#define ull unsigned long long
using namespace std;
const int INF=0x3f3f3f3f;
typedef pair<ll,ll> PLL;
typedef pair<int,int>PII;
ll gcd(ll a,ll b)
{
    if(b) while((a%=b)&&(b%=a));
    return a+b;
}//最大公约数函数
ll spid(ll a,ll b,ll p)
{
    ll ans=1;
    while(b)
    {
        if(b&1)ans=ans*a%p;
        b>>=1;
        a=a*a%p;
    }
    return ans;
}//快速幂函数
///泡沫在阳光下闪烁,像星辰在寂静得夜空中闪耀

///秋雨
const ll N=2e5+10;
vector<ll>go[N];
ll dfn[N];
ll cnt;
stack<ll>st;
ll vis[N];///看某个点是否入栈
ll low[N];
ll _cnt;
ll sum[N];///强连通分量权值记录
ll belong[N];///该点属于哪个强连通分量
ll sig[N];///强连通分量可到标记点
///正常有两种存法
/*{
   1. 写个belong[]数组,表示第i个点属于belong[i]的强连通分量里
   2. 写vector[][]数组,vector[i]存的是第i个强连通分量所有的点集
}*/
void tanjan(ll u)
{
    cnt++;
    dfn[u]=low[u]=cnt;
    st.push(u);
    vis[u]=1;
    for(auto i:go[u])
    {
        if(dfn[i]==0)
        {
            tanjan(i);
            low[u]=min(low[u],low[i]);
        }
        else if(vis[i])///如果i在栈中,那么i一定是u的祖先节点
        {
            low[u]=min(low[u],dfn[i]);
        }
    }
    if(low[u]==dfn[u])
    {
        _cnt++;
        while(st.top()!=u)
        {
            sum[_cnt]++;///加的是权值
            vis[st.top()]=0;
            belong[st.top()]=_cnt;
            st.pop();
        }
        sum[_cnt]++;///他本身的权值
        belong[u]=_cnt;
        vis[u]=0;
        st.pop();
    }
}
void solve()
{
    ll n,m;cin>>n>>m;
    for(int i=1;i<=m;i++)
    {
        ll u,v;cin>>u>>v;
        go[u].pb(v);
    };
    for(int i=1;i<=n;i++)
    {
        if(!dfn[i])
            tanjan(i);
    }
    for(int u=1;u<=n;u++)
    {
        for(auto v:go[u])
        {
            if(belong[u]!=belong[v])
            {
                sig[belong[v]]=1;
            }
        }
    }
    ll ans=0;
//    cout<<_cnt<<'\n';
    for(int i=1;i<=_cnt;i++)
    {
        ans+=(sig[i]==0);
    }
    cout<<ans<<'\n';
}
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    int t=1;
//    cin>>t;
    while(t--)
    {
        solve();
    }
}
///在秋天邂逅, 在春天发芽,在夏天壮大,在秋天萧瑟,在冬天萎缩,

///而后,春天再度归来。

缩点模板题--p3387 模板 缩点

#include<bits/stdc++.h>
#define endl '\n'
#define ll int
#define int int
#define double long double
#define Int __int128
#define pb push_back
#define eb emplace_back
#define MAX_LOG 21
#define ff first
#define ss second
#define M 5005
#define ull unsigned long long
using namespace std;
const int INF=0x3f3f3f3f;
typedef pair<ll,ll> PLL;
typedef pair<int,int>PII;
ll gcd(ll a,ll b)
{
    if(b) while((a%=b)&&(b%=a));
    return a+b;
}//最大公约数函数
ll spid(ll a,ll b,ll p)
{
    ll ans=1;
    while(b)
    {
        if(b&1)ans=ans*a%p;
        b>>=1;
        a=a*a%p;
    }
    return ans;
}//快速幂函数
///泡沫在阳光下闪烁,像星辰在寂静得夜空中闪耀

///秋雨
const ll N=2e5+10;
vector<ll>go[N];///初始邻接表存图
ll dfn[N];///dfs序的存储
ll cnt;///dfs序的分配
stack<ll>st;
ll vis[N];///看某个点是否入栈
ll low[N];
ll _cnt;///强连通分量数量记录变量
ll sum[N];///强连通分量权值记录
ll belong[N];///该点属于哪个强连通分量
ll sig[N];///强连通分量可到标记点
///正常有两种存法
/*{
   1. 写个belong[]数组,表示第i个点属于belong[i]的强连通分量里
   2. 写vector[][]数组,vector[i]存的是第i个强连通分量所有的点集
}*/
ll a[N];///单点权值记录点
void tanjan(ll u)
{
    cnt++;
    dfn[u]=low[u]=cnt;
    st.push(u);
    vis[u]=1;
    for(auto i:go[u])
    {
        if(dfn[i]==0)
        {
            tanjan(i);
            low[u]=min(low[u],low[i]);
        }
        else if(vis[i])///如果i在栈中,那么i一定是u的祖先节点
        {
            low[u]=min(low[u],dfn[i]);
        }
    }
    if(low[u]==dfn[u])
    {
        _cnt++;
        while(st.top()!=u)
        {
            sum[_cnt]+=a[st.top()];///加的是权值
            vis[st.top()]=0;
            belong[st.top()]=_cnt;
            st.pop();
        }
        sum[_cnt]+=a[st.top()];///他本身的权值
        belong[u]=_cnt;
        vis[u]=0;
        st.pop();
    }
}
vector<ll>GO[N];
ll du[N];
ll rem[N];///记录走过的点,给dfs用,记忆化搜索
bool remv[N];///记录是否走过
ll dfs(ll u,ll fa)
{
    if(remv[u])return rem[u];///记忆化搜索
    ll now=sum[u];
    if(GO[u].empty())return now;
    ll x=now;
    for(auto i:GO[u])
    {
        now=max(now,x+dfs(i,u));
    }
    rem[u]=now;
    remv[u]=1;
    return now;
}
void solve()
{
    ll n,m;cin>>n>>m;
    for(int i=1;i<=n;i++)cin>>a[i];
    for(int i=1;i<=m;i++)
    {
        ll u,v;cin>>u>>v;
        go[u].pb(v);
    };
    for(int i=1;i<=n;i++)
    {
        if(!dfn[i])
            tanjan(i);
    }///缩点
    for(int i=1;i<=n;i++)
    {
        for(auto j:go[i])
        {
            if(belong[i]!=belong[j])
            {
                GO[belong[i]].pb(belong[j]);///新图建边
        ///如果不是同一个强连通分量就说明这两个强连通分量有边
                du[belong[j]]++;
            }
        }
    }
    ///  关于DAG有向无环图的跑最长路
    ll ans=0;
    for(int i=1;i<=_cnt;i++)
    {
        ans=max(dfs(i,-1),ans);
    }
    cout<<ans<<'\n';
}
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    int t=1;
//    cin>>t;
    while(t--)
    {
        solve();
    }
}
///在秋天邂逅, 在春天发芽,在夏天壮大,在秋天萧瑟,在冬天萎缩,

///而后,春天再度归来。

二分&&三分

        二分
while(l<r)///靠左
{
    ll mid=l+r>>1;
    if(check(mid))r=mid;
    else l=mid+1;
}
while(l<r)///靠右
{
    ll mid=l+r+1>>1;
    if(check(mid))l=mid;
    else r=mid-1;
}
        三分
while(l<r)
{
    ll midl=l+(r-l)/3;
    ll midr=r-(r-l)/3;
    if(check(midl)>check(midr)) l=midl+1;
    else r=midr-1;
}
///检查l和r,注意保证l和r合法

二分不一定比三分更优(codeforce 964 div4 G2)

米勒-拉宾素性检验(MillerRabbin)--时间复杂度(O(logn))

bool check(const ll a,const ull p)
{
    ull d=p-1,get=spid(a,d,p);
    if(get!=1) return 1;//特判 d=p-1 的情况
    while((d&1)^1)
        if(d>>=1,(get=spid(a,d,p))==p-1) return 0;//先 d/=2,再计算快速幂
        else if(get!=1) return 1;
    return 0;
}
const ll test[]= {2,3,5,7,11,13,17,19,23,29,31,37};
bool miller_rabin(const ull p)///使用的地方,写完这么一坨,然后写个miller_rabin(x)就可以判断x是不是质数
{
    if(p>40)
    {
        for(auto i:test)
            if(check(i,p)) return 0;
        return 1;
    }
    for(auto i:test)
        if(p==i) return 1;
    return 0;
}

为了方便使用理解,这边贴一下判断素数的入门题

///洛谷 :B2085 第 n 小的质数
#include<bits/stdc++.h>
#define endl '\n'
#define ll long long
#define int long long
#define double long double
#define Int __int128
#define pb push_back
#define eb emplace_back
#define MAX_LOG 21
#define ff first
#define ss second
#define M 5005
#define RI register int
#define CI const int&
#define ull unsigned long long
using namespace std;
const int INF=0x3f3f3f3f;
typedef pair<ll,ll> PLL;
typedef pair<int,int>PII;
ll gcd(ll a,ll b)
{
    if(b) while((a%=b)&&(b%=a));
    return a+b;
}//最大公约数函数
ll spid(ll a,ll b,ull p)
{
    ll ans=1;
    while(b)
    {
        if(b&1)ans=ans*a%p;
        b>>=1;
        a=a*a%p;
    }
    return ans;
}//快速幂函数
///泡沫在阳光下闪烁,像星辰在寂静得夜空中闪耀

///秋雨
const ll N=2e5+10;
bool check(const ll a,const ull p)
{
    ull d=p-1,get=spid(a,d,p);
    if(get!=1) return 1;//特判 d=p-1 的情况
    while((d&1)^1)
        if(d>>=1,(get=spid(a,d,p))==p-1) return 0;//先 d/=2,再计算快速幂
        else if(get!=1) return 1;
    return 0;
}
const ll test[]= {2,3,5,7,11,13,17,19,23,29,31,37};
bool miller_rabin(const ull p)
{
    if(p>40)
    {
        for(auto i:test)
            if(check(i,p)) return 0;
        return 1;
    }
    for(auto i:test)
        if(p==i) return 1;
    return 0;
}
void solve()
{
    ll n;cin>>n;
    ll cnt=0;
    ll now=1;
    while(cnt<n)
    {
        if(miller_rabin(now++))cnt++;
    }
    now--;
    cout<<now<<'\n';
}
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    int t=1;
    //cin>>t;
    while(t--)
    {
        solve();
    }
}
///在秋天邂逅, 在春天发芽,在夏天壮大,在秋天萧瑟,在冬天萎缩,

///而后,春天再度归来。

并查集

ll father[N];///第i个人的父亲是 father[i],当然,习惯写成fa[i]
ll find(ll x)
{
    if(father[x]==x)return x;///如果这个人没有指定的父亲,那就返回他本身,否则就去找他父亲
    else return father[x]=find(father[x]);///递归式写法,把经历过的点都处理了。
    ///找到的父亲就更新father[x]啦
}

DFS求因子--时间复杂度O(n^1/4)

#include<bits/stdc++.h>
#define endl '\n'
#define ll long long
#define int long long
#define double long double
#define Int __int128
#define pb push_back
#define eb emplace_back
#define MAX_LOG 21
#define ff first
#define ss second
#define M 5005
#define RI register int
#define CI const int&
#define ull unsigned long long
using namespace std;
const int INF=0x3f3f3f3f;
typedef pair<ll,ll> PLL;
typedef pair<int,int>PII;
ll gcd(ll a,ll b)
{
    if(b) while((a%=b)&&(b%=a));
    return a+b;
}//最大公约数函数
ll spid(ll a,ll b,ull p)
{
    ll ans=1;
    while(b)
    {
        if(b&1)ans=(Int)ans*a%p;
        b>>=1;
        a=(Int)a*a%p;
    }
    return ans;
}//快速幂函数
///泡沫在阳光下闪烁,像星辰在寂静得夜空中闪耀

///秋雨
const ll N=2e5+10;
bool check(const ll a,const ull p)
{
    ull d=p-1,get=spid(a,d,p);
    if(get!=1) return 1;//特判 d=p-1 的情况
    while((d&1)^1)
        if(d>>=1,(get=spid(a,d,p))==p-1) return 0;//先 d/=2,再计算快速幂
        else if(get!=1) return 1;
    return 0;
}
const ll test[]= {2,3,5,7,11,13,17,19,23,29,31,37};
bool miller_rabin(const ll p)
{
    if(p>40)
    {
        for(auto i:test)
            if(check(i,p)) return 0;
        return 1;
    }
    for(auto i:test)
        if(p==i) return 1;
    return 0;
}
mt19937 rng((unsigned int) chrono::steady_clock::now().time_since_epoch().count());
///产生随机数
ll pollard_rho(ll x)
{
    ll s=0,t=0;
    ll c=(ll)(rng())%(x-1)+1;
    ll val = 1;
    for(int goal=1; ; goal<<=1,s=t,val=1)
    {
        for (int step=1; step<=goal; step++)
        {
            t=((Int)(t)*t+c)%x;
            val=(Int)(val)*abs(t-s)%x;
            if(step%127==0)
            {
                ll g=gcd(val,x);
                if(g>1)
                {
                    return g;
                }
            }
        }
        ll g=gcd(val, x);
        if(g>1)
        {
            return g;
        }
    }
}

map<ll,ll> getprimes(ll x)
{
    map<ll,ll> p;
    function<void(ll)>get=[&](ll x)
    {
        if(x<2)
        {
            return;
        }
        if (miller_rabin(x))
        {
            p[x]++;
            return;
        }
        ll mx = pollard_rho(x);
        get(x/mx);
        get(mx);
    };
    get(x);
    return p;
}

vector<ll>getfac(ll x)///获取非凡因子
{
    vector<ll>fac;
    auto primes =getprimes(x);
    vector<PLL> tmp(primes.begin(),primes.end());
    ll len=tmp.size();
    function<void(ll,ll)>dfs=[&](ll st,ll x)
    {
        if(st==len)
        {
            fac.eb(x);
            return;
        }
        ll p = 1;
        for(int i=0; i<=tmp[st].ss; i++)
        {
            if (i != 0)
            {
                p *= tmp[st].ff;
            }
            dfs(st+1,x*p);
        }
    };
    dfs(0, 1);
    return fac;
}
void solve()
{
    ll n;
    cin >> n;
    auto ans=getfac(n);
    sort(ans.begin(), ans.end());
    ans.erase(unique(ans.begin(), ans.end()), ans.end());///去重
    ///求出来的因子
    ///ans是因子存放处
    cout<<ans.size()<<'\n';
    for(auto i:ans)
    {
        cout<<i<<' ';
    }cout<<'\n';
}
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    int t=1;
//    cin>>t;
    while(t--)
    {
        solve();
    }
}
///在秋天邂逅, 在春天发芽,在夏天壮大,在秋天萧瑟,在冬天萎缩,

///而后,春天再度归来。

计算n以内的素数个数,时间复杂度(O(n^{2/3}))->n<=1e12

数组N开根号n大小

#include<bits/stdc++.h>
#define endl '\n'
#define ll long long
#define int long long
#define double long double
#define Int __int128
#define pb push_back
#define eb emplace_back
#define MAX_LOG 21
#define ff first
#define ss second
#define RI register int
#define CI const int&
#define ull unsigned long long
using namespace std;
const int INF=0x3f3f3f3f;
typedef pair<ll,ll> PLL;
typedef pair<int,int>PII;
ll gcd(ll a,ll b)
{
    if(b) while((a%=b)&&(b%=a));
    return a+b;
}//最大公约数函数
ll spid(ll a,ll b,ull p)
{
    ll ans=1;
    while(b)
    {
        if(b&1)ans=(Int)ans*a%p;
        b>>=1;
        a=(Int)a*a%p;
    }
    return ans;
}//快速幂函数
///泡沫在阳光下闪烁,像星辰在寂静得夜空中闪耀

///秋雨
const ll N=5e6+10;
bool np[N];
int prime[N], pi[N];

int getprime()
{
    int cnt = 0;
    np[0] = np[1] = true;
    pi[0] = pi[1] = 0;
    for(int i = 2; i < N; ++i)
    {
        if(!np[i]) prime[++cnt] = i;
        pi[i] = cnt;
        for(int j = 1; j <= cnt && i * prime[j] < N; ++j)
        {
            np[i * prime[j]] = true;
            if(i % prime[j] == 0)   break;
        }
    }
    return cnt;
}
const int M = 7;
const int PM = 2 * 3 * 5 * 7 * 11 * 13 * 17;
int phi[PM + 1][M + 1], sz[M + 1];
void init()
{
    getprime();
    sz[0] = 1;
    for(int i = 0; i <= PM; ++i)  phi[i][0] = i;
    for(int i = 1; i <= M; ++i)
    {
        sz[i] = prime[i] * sz[i - 1];
        for(int j = 1; j <= PM; ++j)
        {
            phi[j][i] = phi[j][i - 1] - phi[j / prime[i]][i - 1];
        }
    }
}
ll sqrt2(ll x)
{
    ll r = (ll)sqrt(x - 0.1);
    while(r * r <= x)   ++r;
    return (ll)(r - 1);
}
ll sqrt3(ll x)
{
    ll r = (ll)cbrt(x - 0.1);
    while(r * r * r <= x)   ++r;
    return (ll)(r - 1);
}
ll getphi(ll x, ll s)
{
    if(s == 0)  return x;
    if(s <= M)  return phi[x % sz[s]][s] + (x / sz[s]) * phi[sz[s]][s];
    if(x <= prime[s]*prime[s])   return pi[x] - s + 1;
    if(x <= prime[s]*prime[s]*prime[s] && x < N)
    {
        ll s2x = pi[sqrt2(x)];
        ll ans = pi[x] - (s2x + s - 2) * (s2x - s + 1) / 2;
        for(int i = s + 1; i <= s2x; ++i)
        {
            ans += pi[x / prime[i]];
        }
        return ans;
    }
    return getphi(x, s - 1) - getphi(x / prime[s], s - 1);
}
ll getpi(ll x)
{
    if(x < N)   return pi[x];
    ll ans = getphi(x, pi[sqrt3(x)]) + pi[sqrt3(x)] - 1;
    for(int i = pi[sqrt3(x)] + 1, ed = pi[sqrt2(x)]; i <= ed; ++i)
    {
        ans -= getpi(x / prime[i]) - i + 1;
    }
    return ans;
}
ll lehmer_pi(ll x)
{
    if(x < N)   return pi[x];
    ll a = (ll)lehmer_pi(sqrt2(sqrt2(x)));
    ll b = (ll)lehmer_pi(sqrt2(x));
    ll c = (ll)lehmer_pi(sqrt3(x));
    ll sum = getphi(x, a) + (ll)(b + a - 2) * (b - a + 1) / 2;
    for (int i = a + 1; i <= b; i++)
    {
        ll w = x / prime[i];
        sum -= lehmer_pi(w);
        if (i > c) continue;
        ll lim = lehmer_pi(sqrt2(w));
        for (int j = i; j <= lim; j++)
        {
            sum -= lehmer_pi(w / prime[j]) - (j - 1);
        }
    }
    return sum;
}
void solve()
{
    ll n;
    cin>>n;
    cout<<lehmer_pi(n)<<'\n';
}
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    int t=1;
    init();
    cin>>t;
    while(t--)
    {
        solve();
    }
}
///在秋天邂逅, 在春天发芽,在夏天壮大,在秋天萧瑟,在冬天萎缩,

///而后,春天再度归来。

计算n以内的素数个数,时间复杂度(n^(2/3))-->短了很多有没有!

数组开根号n大小

#include<bits/stdc++.h>
#define endl '\n'
#define ll long long
#define int long long
#define double long double
#define Int __int128
#define pb push_back
#define eb emplace_back
#define MAX_LOG 21
#define ff first
#define ss second
#define RI register int
#define CI const int&
#define ull unsigned long long
using namespace std;
const int INF=0x3f3f3f3f;
typedef pair<ll,ll> PLL;
typedef pair<int,int>PII;
ll gcd(ll a,ll b)
{
    if(b) while((a%=b)&&(b%=a));
    return a+b;
}//最大公约数函数
ll spid(ll a,ll b,ull p)
{
    ll ans=1;
    while(b)
    {
        if(b&1)ans=(Int)ans*a%p;
        b>>=1;
        a=(Int)a*a%p;
    }
    return ans;
}//快速幂函数
///泡沫在阳光下闪烁,像星辰在寂静得夜空中闪耀

///秋雨
const ll N=5e6+10;
ll num[N], value[N];
ll deal(ll n)
{
    ll m;
    for(m=1; m*m<=n; ++m)
        num[m] = n/m-1;
    for(int i=1; i<=m; ++i)
        value[i] = i-1;
    for(int i=2; i<=m; ++i)
	{
        if(value[i] == value[i-1]) continue;
        for(int j=1; j<=min(m-1,n/i/i); ++j)
            if(i*j < m) num[j] -= num[i*j]-value[i-1];
            else num[j] -= value[n/i/j]-value[i-1];
        for(int j=m; j>=i*i; --j)
            value[j] -= value[j/i]-value[i-1];
    }
    return num[1];
}
void solve()
{
    ll n;cin>>n;
    cout<<deal(n)<<'\n';
}
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    ///预处理处
    int t=1;
//    cin>>t;
    while(t--)
    {
        solve();
    }
}
///在秋天邂逅, 在春天发芽,在夏天壮大,在秋天萧瑟,在冬天萎缩,

///而后,春天再度归来。

逆元

费马小定理----针对模数为质数求逆元

///通常逆元标记为inv变量(也可能是我养成的习惯)
#define Int __int128
ll spid(ll a,ll b,ull p)
{
    ll ans=1;
    while(b)
    {
        if(b&1)ans=(Int)ans*a%p;///学乖了,以后快速幂我必加一个__int128
        b>>=1;
        a=(Int)a*a%p;
    }
    return ans;
}//快速幂函数
ll get_inv(ll x)
{
    return spid(x,p-2,p);
}

扩展欧几里得--针对任意数,但不保证逆元真的存在

void exgcd(ll a,ll b,ll &x,ll &y)
{
    if(!b)x=1,y=0;
    else
        exgcd(b,a%b,y,x),y-=a/b*x;
}
void solve()
{
    ll a,p;cin>>a>>p;
    ll x,y;///y为最后无关但中途必须存在的变量
    exgcd(a,p,x,y);///扩展欧几里得求逆元
    x=(x%p+p)%p;///取正数
    ///x是a在模p下的逆元
    cout<<x<<'\n';
}

线性求逆元 --->O(n)时间复杂度内处理好1~n的逆元(前提是mod 是一个质数)

int inv[mod+5];
void get_Inv(int mod)
{
	inv[1]=1;
	for(int i=2;i<mod;i++)
		inv[i]=(mod-mod/i)*inv[mod%i]%mod;
}

图的建边

链式前向星建边
int head[N];
struct edge
{
    int next;///下一条边的位置(下标)
    int to;///这条边指向的另一个端点
    int value;    /// 若果有的话
} e[N];
int cnt = 0;
void add_edge(int u, int v, int w)
{
    cnt++;
    e[cnt].to=v;
    e[cnt].value=w;           /// 若果有的话
    e[cnt].next=head[u];///记录之前存边的下标
    head[u]=cnt;
}
///遍历以u为起始点的边
for (int i = head[u]; i != 0; i = e[i].next)
{
    ...
}
邻接表
vector<pair<int,int>>go[n+1];
///建边
int u,v,value;///value如果存在的话
go[u].emplac_back(v,value);///加边
///遍历以u为起始点的边
for(auto i:go[u])
{
    ...
}
邻接矩阵
int go[N][N];
///建边
int u,v,value;
go[u][v]=value;
///访问u->v边 的权值 
go[u][v];

最近公共祖先(LCA)

倍增算法(在线
#include<bits/stdc++.h>
#define endl '\n'
#define ll int
//#define int long long
#define double long double
#define Int __int128
#define pb push_back
#define eb emplace_back
#define MAX_LOG 21
#define ff first
#define ss second
#define RI register int
#define CI const int&
#define ull unsigned long long
using namespace std;
const int INF=0x3f3f3f3f;
typedef pair<ll,ll> PLL;
typedef pair<int,int>PII;
ll gcd(ll a,ll b)
{
    if(b) while((a%=b)&&(b%=a));
    return a+b;
}//最大公约数函数
ll spid(ll a,ll b,ull p)
{
    ll ans=1;
    while(b)
    {
        if(b&1)ans=(Int)ans*a%p;
        b>>=1;
        a=(Int)a*a%p;
    }
    return ans;
}//快速幂函数
///泡沫在阳光下闪烁,像星辰在寂静得夜空中闪耀

///秋雨
const ll N=2e6+10;
vector<ll>go[N];
int depth[N], fa[N][30], lg[N];
///fa[i][j]表示节点i的2^j级祖先
void dfs(int u, int fath) 
///u表示当前节点,fath表示它的父亲节点
{
    fa[u][0]= fath;
    depth[u]= depth[fath] + 1;///处理深度
    for(int i = 1; i <= lg[depth[u]]; ++i)
        fa[u][i] = fa[fa[u][i-1]][i-1];
///意思是u的2^i祖先等于u的2^(i-1)祖先的2^(i-1)祖先
///因为 2^i = 2^(i-1) + 2^(i-1)
    for(auto i: go[u])
        if(i!= fath) dfs(i, u);
}
int LCA(int x, int y)
{
    if(depth[x]< depth[y])swap(x, y);///x的深度大于y
    while(depth[x]> depth[y])
        x=fa[x][lg[depth[x]-depth[y]]-1];///让x与y跳到同一深度
    if(x==y)return x;///如果x是y的祖先,那么LCA必然是x,返回x
    ///因为跳跃过程只有更深的x在做
    for(int k= lg[depth[x]]- 1; k>= 0; --k)
        if(fa[x][k]!= fa[y][k])
            x= fa[x][k], y= fa[y][k];
///因为我们要跳到它们LCA的下面一层,所以它们肯定不相等,如果不相等就跳过去。
    return fa[x][0];
}

void solve()
{
    int n,m,s;
    cin>>n>>m>>s;
    for(int i=1;i<=n;i++)go[i].clear();
    for(int i=1; i<=n-1; i++)
    {
        int x,y;
        cin>>x>>y;
        go[x].eb(y);
        go[y].eb(x);
    }
    for(int i=1; i<=n; i++)
        lg[i]=lg[i-1]+(1<<lg[i-1]==i);
    ///预先算出log_2(i)+1的值,用的时候直接调用就可以了
    dfs(s,0);
    for(int i = 1; i <= m; ++i)
    {
        int x, y;
        cin>>x>>y;
        cout<<LCA(x,y)<<'\n';
    }
}
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    int t=1;
    // cin>>t;
    while(t--)
    {
        solve();
    }
}
///在秋天邂逅, 在春天发芽,在夏天壮大,在秋天萧瑟,在冬天萎缩,

///而后,春天再度归来。

最短路-迪杰斯特拉

#include<bits/stdc++.h>
#define endl '\n'
#define ll int
#define Int __int128
#define pb push_back
#define N (int)1e6+10
#define MAX_LOG 21
#define ff first
#define ss second
#define M (int)1e4+10
#define ull unsigned long long
using namespace std;
const double PI=3.1415926535897932385;
const ll LLMAX=9223372036854775807ll;
const ll LLMIN=-9223372036854775808ll;
//const int MAX_INT=0x3f3f3f3f;
const int IIMAX=2147483647;
const int IIMIN=-2147483648;
const ll p=998244353;
const ll mod=1e9+7;
const int INF=0x3f3f3f3f;
typedef pair<ll,ll> PLL;

ll gcd(ll a,ll b)
{
    if(b) while((a%=b)&&(b%=a));
    return a+b;
}//最大公约数函数
ll spid(ll a,ll b,ll p)
{
    ll ans=1;
    while(b)
    {
        if(b&1)ans=ans*a%p;
        b>>=1;
        a=a*a%p;
    }
    return ans;
}//快速幂函数
///小香猪牌代码
///迪杰斯特拉优化
struct node
{
    ll v,next,w;
}edge[N];
ll cnt;bool vis[N];ll dis[N],head[N];
void add(ll u,ll v,ll w)//起点,终点,距离,链式前向星建图
{
    edge[cnt].w=w;
    edge[cnt].v=v;
    edge[cnt].next=head[u];
    head[u]=cnt++;
}
void dijkstra(ll n,ll s)
{
    priority_queue<PLL,vector<PLL>,greater<PLL>>q;
    memset(dis,INF,sizeof(dis));
    q.push({0,1});
    dis[s]=0;
    while(!q.empty())
    {
        PLL temp = q.top();//记录堆顶,即堆内最小的边并将其弹出
        q.pop();
        int u = temp.second;//点
        if(vis[u]) continue;//如果被访问过,就跳过
        vis[u]=true;//标记
        for(int i = head[u];i!=-1;i=edge[i].next)//搜索堆顶的所有连边
        {
            int v = edge[i].v;
            if(dis[v]>dis[u]+edge[i].w)//松弛操作
            {
                dis[v]=dis[u]+edge[i].w;
                q.push({dis[v],v});//把新遍历的点加到堆中
            }
        }
    }
    for(int i=1;i<=n;i++)
    cout<<dis[i]<<' ';
}
void solve()
{
    ll n,m,s;cin>>n>>m>>s;
    memset(head,-1,sizeof(head));
    for(int i = 0;i<m;i++)
    {
        ll u,v,w;
        cin>>u>>v>>w;
        add(u,v,w);
    }
    dijkstra(n,s);
}

signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);cout.tie(nullptr);
    int t=1;
//    cin>>t;
    while(t--)
    {
        solve();
    }
}

树的直径

#include<bits/stdc++.h>
#define endl '\n'
#define ll long long
#define int long long
#define double long double
#define Int __int128
#define pb push_back
#define eb emplace_back
#define MAX_LOG 21
#define ff first
#define ss second
#define RI register int
#define CI const int&
#define ull unsigned long long
using namespace std;
const int INF=0x3f3f3f3f;
typedef pair<ll,ll> PLL;
typedef pair<int,int>PII;
ll gcd(ll a,ll b)
{
    if(b) while((a%=b)&&(b%=a));
    return a+b;
}//最大公约数函数
ll spid(ll a,ll b,ull p)
{
    ll ans=1;
    while(b)
    {
        if(b&1)ans=(Int)ans*a%p;
        b>>=1;
        a=(Int)a*a%p;
    }
    return ans;
}//快速幂函数
///泡沫在阳光下闪烁,像星辰在寂静得夜空中闪耀

///秋雨
const ll N=2e5+10;
ll dis[N];
vector<ll>go[N];
void dfs(ll u,ll fa) {
	dis[u] = dis[fa] + 1;
	for (int i: go[u]) {
		if (i!= fa)dfs(i, u);
	}
	return;
}
void solve()
{
    ll n;
    cin>>n;
    for(int i=0;i<=n;i++)go[i].clear();
    for(int i = 1; i<n; i++)
    {
        ll u,v;
        cin>>u>>v;
        go[u].eb(v);
        go[v].eb(u);
    }
    dis[1]=0;
    dfs(1, 0);
    ll st=1,m_dis=0;
    for(int i=2; i<= n; i++) if (dis[i] > dis[st])st= i;///树的一个端点
    dfs(st,0);
    for(int i= 1; i<= n; i++)m_dis= max(m_dis, dis[i]);
    ///m_dis就是树的直径
}

signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    int t=1;
    cin>>t;
    while(t--)
    {
        solve();
    }
}
///在秋天邂逅, 在春天发芽,在夏天壮大,在秋天萧瑟,在冬天萎缩,

///而后,春天再度归来。

差分&&前缀和:

一维差分:

#include<bits/stdc++.h>
#define ll long long
#define N (ll)1e7+10
using namespace std;
ll a[N];ll sum[N];
void solve()
{
    ll n,m;
    cin>>n>>m;///数组初始长度为n,m次区间修改操作
    for(int i=1;i<=n;i++){cin>>a[i];sum[i]=a[i]-a[i-1];}///读入n个元素,构造差分数组sum
    while(m--)
    {
        ll l,r,k;
        cin>>l>>r>>k;///在区间l~r上加上k
        sum[l]+=k;sum[r+1]-=k;
    }
    for(int i=1;i<=n;i++)
    {
        sum[i]+=sum[i-1];///差分数组恢复
        cout<<sum[i]<<' ';
    }cout<<'\n';///输出差分数组
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(NULL);cout.tie(NULL);
    int t=1;
//    cin>>t;
    while(t--)
    {
        solve();
    }
}

二维差分&&二维前缀和

#include<bits/stdc++.h>
#define endl '\n'
#define ll long long
//#define int long long
#define double long double
#define Int __int128
#define pb push_back
#define eb emplace_back
#define MAX_LOG 21
#define ff first
#define ss second
#define RI register int
#define CI const int&
#define ull unsigned long long
using namespace std;
const int INF=0x3f3f3f3f;
typedef pair<ll,ll> PLL;
typedef pair<int,int>PII;
ll gcd(ll a,ll b)
{
    if(b) while((a%=b)&&(b%=a));
    return a+b;
}//最大公约数函数
ll spid(ll a,ll b,ull p)
{
    ll ans=1;
    while(b)
    {
        if(b&1)ans=(Int)ans*a%p;
        b>>=1;
        a=(Int)a*a%p;
    }
    return ans;
}//快速幂函数
///泡沫在阳光下闪烁,像星辰在寂静得夜空中闪耀

///秋雨
const ll N=2e6+10;
void solve()
{
    ll n,m,q;
    cin>>n>>m>>q;
    vector<vector<ll>>a(n+2,vector<ll>(m+2,0));
    vector<vector<ll>>tu(n+2,vector<ll>(m+2,0));
    for (int i=1; i<=n; i++)
    {
        for (int j=1; j<=m; j++)
        {
            cin>>a[i][j];
            tu[i][j]= a[i][j]-a[i-1][j]-a[i][j-1]+a[i-1][j-1];
            ///二维矩阵转化成差分矩阵
        }
    }
    while(q--)
    {
        ll x1, y1, x2, y2, value;
        cin>>x1>>y1>>x2>>y2>>value;
        tu[x1][y1] += value;
        tu[x1][y2+1] -=value;
        tu[x2+1][y1] -=value;
        tu[x2+1][y2+1] += value;
        ///差分的处理,在(x1,y1)-(x2,y2)矩阵内加上value
    }
    for (int i=1; i<=n; i++)
    {
        for (int j=1; j<=m; j++)
        {
            tu[i][j] += tu[i-1][j]+tu[i][j-1]-tu[i-1][j-1];
            ///矩阵恢复
        }
    }
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            cout<<tu[i][j]<<' ';
        }cout<<'\n';
    }
}
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    int t=1;
    cin>>t;
    while(t--)
    {
        solve();
    }
}
///在秋天邂逅, 在春天发芽,在夏天壮大,在秋天萧瑟,在冬天萎缩,

///而后,春天再度归来。

三维前缀和

for(int i=1;i<=n;i++){
    for(int j=1;j<=n;j++){
        for(int k=1;k<=n;k++){
            sum[i][j][k]=sum[i-1][j][k]+sum[i][j-1][k]+sum[i][j][k-1]-sum[i-1][j-1][k]-sum[i-1][j][k-1]-
                sum[i][j-1][j-1]+sum[i-1][j-1][k-1]+a[i][j][k];
        }
    }
}

RMQ查询区间最值

st表的构建:建表O(nlogn) 查询O (log n)

#include<bits/stdc++.h>
#define endl "\n"
#define Int __int128
#define ll long long
#define fs first
#define se second
#define pb push_back
#define N (int)1e6+10
#define MAX_LOG 21
//const ll p=998244353;
ll gcd(ll a,ll b)
{
    if(b) while((a%=b)&&(b%=a));
    return a+b;
}//最大公约数函数
ll spid(ll a,ll b,ll p)
{
    ll ans=1;
    while(b)
    {
        if(b&1)ans=ans*a%p;
        b>>=1;
        a=a*a%p;
    }
    return ans;
}//快速幂函数
using namespace std;
ll a[N];ll st[N][MAX_LOG];
ll log_2[N];//预处理log2,虽然C++本身有log2
//函数,但是还是推荐预处理出来
void init()
{
    log_2[1]=0;log_2[2]=1;
    for(int i=3;i<N;i++)
        log_2[i]=log_2[i>>1]+1;
    //log2 x= log2 x/2 +1
}
///ST[1][2]  i+(1<<j)-1<=n
///ST[i][j]=max(ST[i][j-1],ST[i+(1<<(j-1))][j-1]);
///1 2 3 4 5 6 7 8
void solve()
{
    init();//预处理log_2
    ll n,m;
    cin>>n>>m;
    for(int i=1;i<=n;i++)
        cin>>st[i][0];
    //预处理st表
    for(int j=1;j<=MAX_LOG;j++)
    {
        for(int i=1;i+(1<<j)-1<=n;i++)
        {
            st[i][j]=max(st[i][j-1],st[i+(1<<(j-1))][j-1]);
        }
    }
    while(m--)
    {
        ll l,r;
        cin>>l>>r;
        ll x=log_2[r-l+1];
        cout<<max(st[l][x],st[r-(1<<x)+1][x])<<'\n';
    }
}

signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(NULL);cout.tie(NULL);
    int T=1;
//    cin>>T;
    while(T--)
        solve();
}

逆序数模板:

#include<bits/stdc++.h>
#define endl '\n'
#define ll long long
#define int long long
#define double long double
#define Int __int128
#define pb push_back
#define eb emplace_back
#define MAX_LOG 21
#define ff first
#define ss second
#define RI register int
#define CI const int&
#define ull unsigned long long
using namespace std;
const int INF=0x3f3f3f3f;
typedef pair<ll,ll> PLL;
typedef pair<int,int>PII;
ll gcd(ll a,ll b)
{
    if(b) while((a%=b)&&(b%=a));
    return a+b;
}//最大公约数函数
ll spid(ll a,ll b,ull p)
{
    ll ans=1;
    while(b)
    {
        if(b&1)ans=(Int)ans*a%p;
        b>>=1;
        a=(Int)a*a%p;
    }
    return ans;
}//快速幂函数
///泡沫在阳光下闪烁,像星辰在寂静得夜空中闪耀

///秋雨
const ll N=2e5+10;

int a[N];
int tep[N];
int sum=0;
void conquer(int l,int mid,int r)
{
    int pos1=l,pos2=mid+1;
    int i=l;
    while(pos1<=mid&&pos2<=r)
    {
        if(a[pos1]<=a[pos2])tep[i++]=a[pos1++];
        else
        {
            sum+=(mid-pos1+1);
            tep[i++]=a[pos2++];
        }
    }
    for(int j=pos1; j<=mid; j++)tep[i++]=a[j];
    for(int j=pos2; j<=r; j++)tep[i++]=a[j];
    for(int j=l; j<=r; j++)a[j]=tep[j];
}
void divide(int l,int r)
{
    if(l==r)return;
    int mid=(l+r)>>1;
    divide(l,mid);
    divide(mid+1,r);
    conquer(l,mid,r);
}
void solve()
{
    int n;
    cin>>n;///长度为n的数组
    for(int i=1; i<=n; i++)cin>>a[i];
    divide(1,n);
    cout<<sum<<'\n';///该数组的逆序数
}
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    int t=1;
//    cin>>t;
    while(t--)
    {
        solve();
    }
}
///在秋天邂逅, 在春天发芽,在夏天壮大,在秋天萧瑟,在冬天萎缩,

///而后,春天再度归来。

区间合并:

#include<bits/stdc++.h>
#define endl '\n'
#define ll long long
#define Int __int128
#define pb push_back
#define N (int)1e6+10
#define MAX_LOG 21
#define ff first
#define ss second
using namespace std;
//const ll p=998244353;
const ll MOD=1e9+7;
//typedef long long ll;
const int MAX_INT=0x3f3f3f3f;
typedef pair<ll,ll> PLL;
ll gcd(ll a,ll b)
{
    if(b) while((a%=b)&&(b%=a));
    return a+b;
}//最大公约数函数
ll spid(ll a,ll b,ll p)
{
    ll ans=1;
    while(b)
    {
        if(b&1)ans=ans*a%p;
        b>>=1;
        a=a*a%p;
    }
    return ans;
}//快速幂函数
//map<ll,ll>mp;
///区间dp
vector<PLL>v,ans;
void solve()
{
    ll n;
    cin>>n;
    while(n--)
    {
        ll l,r;
        cin>>l>>r;
        v.pb({l,r});///区间
    }
    sort(v.begin(),v.end());
    ll be=0;ll ed=0;
    for(auto it:v)
    {
        if(ed<it.ff)
        {
            if(ed!=0)ans.pb({be,ed});
            be=it.ff;
            ed=it.ss;
        }
        else ed=max(ed,it.ss);///合并区间
    }
    if(ed!=0)
        ans.push_back({be,ed});
    ///ans为合并后的区间集
    ll sum=0;
    for(auto it:ans)
        sum+=it.ss-it.ff+1;///合并后区间总大小
    cout<<sum<<'\n';
}
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);cout.tie(nullptr);
    int t=1;
//    cin>>t;
    while(t--)
    {
        solve();
    }
}

筛因子&&质数筛

筛因子:

vector<ll>a[M];
// 筛因子 O(n*(ln(n)+0.577))
void init1()///预处理出1~n各自的因子
{
    ll n=2e5;
    for(int i=1;i<=n;i++)
    {
        for(int j=i;j<=n;j+=i)
            a[j].push_back(i);
    }
}
void inti2()//O(sqrt(n))
//筛单个数的因子
{
    ll n;cin>>n;
    vector<ll>p;
    ll y=sqrt(n);
    for(ll i=1;i<=y;i++)
    {
        if(n%i==0)
        {
            p.push_back(i);
            if(i!=n/i)p.push_back(n/i);
        }
    }
    for(auto it:p)
    {
        cout<<it<<' ';
    }
}
void init3()//某个数筛质因子及其个数
{
    ll n;cin>>n;
    map<ll,ll>mp;
    for(int i=2;i<=n>>1;i++)
    {
        while(n%i==0)
        {
            n/=i;
            mp[i]++;
        }
    }
    if(n>1)map[n]++;
}
///不要忘记单个数DFS求因子的n^1/4的随机数做法

质数筛:

vector<ll>p;
bool vis[N];
void get(ll n)//O(n*(log(n))*log(n))///埃氏筛
{
    for(int i=2;i<=n;i++)
    {
        if(!vis[i])
        {
            p.pb(i);
            for(int j=2*i;j<=n;j+=i)
                vis[j]=1;
        }
    }
}
vector<ll>shapi;
void line(ll n)///欧拉筛 O(n)
{
    for(int i=2;i<=n;i++)
    {
        if(!vis[i])shapi.pb(i);
        for(auto x:shapi)
        {
            if(x*i>n)break;
            vis[x*i]=1;
            if(i%x==0)break;
        }
    }
}

树状数组  区间修改 区间查询 建树 n log n 查询 log n

#include<bits/stdc++.h>
#define endl '\n'
#define ll long long
#define int long long
#define double long double
#define Int __int128
#define pb push_back
#define eb emplace_back
#define MAX_LOG 21
#define ff first
#define ss second
#define RI register int
#define CI const int&
#define ull unsigned long long
using namespace std;
const int INF=0x3f3f3f3f;
typedef pair<ll,ll> PLL;
typedef pair<int,int>PII;
ll gcd(ll a,ll b)
{
    if(b) while((a%=b)&&(b%=a));
    return a+b;
}//最大公约数函数
ll spid(ll a,ll b,ull p)
{
    ll ans=1;
    while(b)
    {
        if(b&1)ans=(Int)ans*a%p;
        b>>=1;
        a=(Int)a*a%p;
    }
    return ans;
}//快速幂函数
///泡沫在阳光下闪烁,像星辰在寂静得夜空中闪耀

///秋雨
#define lowbit(x) (x&(-x))
#define cin(x) scanf("%lld",&x);
const ll N=1e6+10;
ll a[N];
ll c1[N], c2[N];
ll n,m;
void add(ll x,ll v)
{
    for(int i= x; i<= n; i+= lowbit(i))
    {
        c1[i]+= v;
        c2[i]+= x* v;
    }
}

ll query(ll x)
{
    ll res= 0;
    for (int i= x; i;i -= lowbit(i))res+= (x + 1)* c1[i]- c2[i];
    return res;
}

void solve()
{
    cin>>n>>m;
    for (int i = 1; i <= n; ++i)
    {
        cin>>a[i];
        add(i, a[i]-a[i-1]);
    }
    ll op;
    while (m--)
    {
        cin>>op;
        if (op==2)///区间查询
        {
            ll l, r;
            cin>>l>>r;
            cout<<query(r) - query(l - 1) << '\n';
        }
        else
        {
            ll l,r,v;
            cin >>l>>r>>v;///区间修改
            add(l, v);add(r+1,-v);
        }
    }
}

signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    int t=1;
    ///预处理处
//    init();
//    cin>>t;
    while(t--)
    {
        solve();
    }
}
///在秋天邂逅, 在春天发芽,在夏天壮大,在秋天萧瑟,在冬天萎缩,

///而后,春天再度归来。

线段树 区间加法 区间查询 建树O(nlog n) 查询 log n

#include<bits/stdc++.h>
#define endl '\n'
#define ll long long
#define Int __int128
#define pb push_back
#define N (int)1e6+10
#define MAX_LOG 21
#define ff first
#define ss second
#define M (int)1e4+10
#define ull unsigned long long
using namespace std;
const double PI=3.1415926535897932385;
const ll LLMAX=9223372036854775807ll;
const ll LLMIN=-9223372036854775808ll;
//const int MAX_INT=0x3f3f3f3f;
const int IIMAX=2147483647;
const int IIMIN=-2147483648;
const ll p=998244353;
const ll mod=1e9+7;
const int INF=0x3f3f3f3f;
typedef pair<ll,ll> PLL;

ll gcd(ll a,ll b)
{
    if(b) while((a%=b)&&(b%=a));
    return a+b;
}//最大公约数函数
ll spid(ll a,ll b,ll p)
{
    ll ans=1;
    while(b)
    {
        if(b&1)ans=ans*a%p;
        b>>=1;
        a=a*a%p;
    }
    return ans;
}//快速幂函数
///泡沫在阳光下闪烁,像星辰在寂静得夜空中闪耀

///秋雨
ll a[N];
ll lazy[N*4];
struct node
{
    ll l,r;
    ll sum;
}tr[N*4];
void build(ll now,ll l,ll r)
{
    tr[now].l=l,tr[now].r=r;
    if(l==r)
    {
        tr[now].sum=a[l];
        return;
    }
    ll mid=l+r>>1;
    if(l<=mid)build(now<<1,l,mid);
    if(mid<r)build(now<<1|1,mid+1,r);
    tr[now].sum=tr[now<<1].sum+tr[now<<1|1].sum;
}
void push_down(ll now,ll l,ll r)
{
    if(lazy[now])
    {
        lazy[now<<1]+=lazy[now];
        lazy[now<<1|1]+=lazy[now];
        ll mid=l+r>>1;
        tr[now<<1].sum+=lazy[now]*(mid-l+1);
        tr[now<<1|1].sum+=lazy[now]*(r-mid);
        lazy[now]=0;
    }
}
void push_up(ll now)
{
    tr[now].sum=tr[now<<1].sum+tr[now<<1|1].sum;
}
void add(ll now,ll x,ll y,ll k)
{
    ll l=tr[now].l,r=tr[now].r;
    if(l==r)
    {
        tr[now].sum+=k;
        return;
    }
    if(l>=x&&r<=y)
    {
        tr[now].sum+=k*(r-l+1);
        lazy[now]+=k;
        return;
    }
    push_down(now,l,r);
    ll mid=l+r>>1;
    if(mid>=x)add(now<<1,x,y,k);
    if(mid<y)add(now<<1|1,x,y,k);
    push_up(now);
}
ll find(ll now,ll x,ll y)
{
    ll l=tr[now].l,r=tr[now].r;
    if(l>=x&&r<=y)
    {
        return tr[now].sum;
    }
    push_down(now,l,r);
    ll mid=l+r>>1;
    ll ans=0;
    if(mid>=x)ans+=find(now<<1,x,y);
    if(mid<y)ans+=find(now<<1|1,x,y);
    return ans;
}
void solve()
{
    ll n,q;cin>>n>>q;
    for(int i=1;i<=n;i++)cin>>a[i];
    build(1,1,n);
    while(q--)
    {
        ll op;cin>>op;
        if(op==1)
        {
            ll x,y,k;cin>>x>>y>>k;
            add(1,x,y,k);
        }else
        {
            ll x,y;cin>>x>>y;
            cout<<find(1,x,y)<<'\n';
        }
    }
}

signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    int t=1;
//    cin>>t;
    while(t--)
    {
        solve();
    }
}
///在秋天邂逅, 在春天发芽,在夏天壮大,在秋天萧瑟,在冬天萎缩,
///而后,春天再度归来。

单调队列

//求m长度区间内的最小值
int a[N];
void solve()
{
   int n,m,i; cin>>n>>m;
   deque<int>q;
   for(i=1;i<=n;i++) cin>>a[i];
   for(i=1;i<=n;i++)
   {
       while(!q.empty()&&a[i]<=a[q.back()]) q.pop_back();
       // 若求区间最大,符号改为>=即可
       q.push_back(i);
       if(q.front()<=i-m) q.pop_front();
       cout<<a[q.front()]<<"\n";
   }
}

字符串哈希(O(n)) 查询O(1)

ull h[N], p[N];
ll P=131;
void init(string &s)
{
    p[0]=1;
    ll n=s.size();
    for(int i=0; i< n; i++ )
   {
        h[i]=h[i-1]*P+s[i];
        p[i]=p[i-1]*P;
   }
}
ull get(int l, int r)
{
    return h[r] - h[l - 1] * p[r - l + 1];
}
///把字符串放进init()里,然后通过get得到字串的哈希值

manacher 最大回文子串(O(n))

ll manacher(string &s)///最大回文子串
{
    ll n=s.size();
    vector<ll>p(2*n+2);
    vector<char>t(2*n+2);
    ll now=0;
    t[++now]='#';
    for(int i=0;i<n;i++)
    {
        t[++now]=s[i];
        t[++now]='#';
    }
    ll mid=0,r=0;
    for(int i=1;i<=now;i++)
    {
        if(i>r)p[i]=1;
        else p[i]=min(p[2*mid-i],r-i+1);
        while(i-p[i]>=1&&i+p[i]<=now&&t[i-p[i]]==t[i+p[i]])p[i]++;
        if(i+p[i]-1>r)mid=i,r=i+p[i]-1;
    }
    ///p[i]:从i开始的最长回文串
    return *max_element(p.begin(),p.end())-1;
}

  • 35
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值