Wind_Flute -- 暮雨笙箫
目录
目录
二分不一定比三分更优(codeforce 964 div4 G2)
米勒-拉宾素性检验(MillerRabbin)--时间复杂度(O(logn))
计算n以内的素数个数,时间复杂度(O())->n<=1e12
计算n以内的素数个数,时间复杂度(n^(2/3))-->短了很多有没有!
线性求逆元 --->O(n)时间复杂度内处理好1~n的逆元(前提是mod 是一个质数)
树状数组 区间修改 区间查询 建树 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<=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;
}