网站下拉菜单代码,网站开发的前后台的步骤分别为,软件开发网站,火龙二合一版本手游传奇文章目录字符串处理后缀数组manacherhashKMP最大最小表达法数论约瑟夫环欧拉函数莫比乌斯反演逆序对归并排序求逆序对素数线性筛欧几里得与扩展欧几里得欧几里得算法#xff1a;扩展欧几里得算法#xff1a;逆元扩展欧几里得费马小定理欧拉定理递推求逆元__int128高精度运算唯…
文章目录字符串处理后缀数组manacherhashKMP最大最小表达法数论约瑟夫环欧拉函数莫比乌斯反演逆序对归并排序求逆序对素数线性筛欧几里得与扩展欧几里得欧几里得算法扩展欧几里得算法逆元扩展欧几里得费马小定理欧拉定理递推求逆元__int128高精度运算唯一分解定理数据结构树链剖分字典树树状数组二维树状数组线段树权值线段树主席树单调栈图论拓扑排序tarjan求割点二分图匹配--匈牙利算法最优匹配网络流问题DinicKM算法最短路径问题dijstra搜索动态规划计算几何其他算法快速输入输出快读快输C大数大数加法大数乘以整形数大数除以整形数大数乘法Java大数A B大整数加法大数阶乘大斐波那契数A/B莫队算法常规莫队带修改莫队字符串处理
后缀数组
全文背诵
#include algorithm
#include cstdio
#include cstring
#include iostreamusing namespace std;const int N 1000010;char s[N];
int n, sa[N], rk[N], oldrk[N 1], id[N], px[N], cnt[N];
// px[i] rk[id[i]]用于排序的数组所以叫 pxbool cmp(int x, int y, int w) {return oldrk[x] oldrk[y] oldrk[x w] oldrk[y w];
}int main() {int i, m 300, p, w;scanf(%s, s 1);n strlen(s 1);for (i 1; i n; i) cnt[rk[i] s[i]];for (i 1; i m; i) cnt[i] cnt[i - 1];for (i n; i 1; --i) sa[cnt[rk[i]]--] i;for (w 1; w n; w 1, m p) { // mp 就是优化计数排序值域for (p 0, i n; i n - w; --i) id[p] i;for (i 1; i n; i)if (sa[i] w) id[p] sa[i] - w;memset(cnt, 0, sizeof(cnt));for (i 1; i n; i) cnt[px[i] rk[id[i]]];for (i 1; i m; i) cnt[i] cnt[i - 1];for (i n; i 1; --i) sa[cnt[px[i]]--] id[i];memcpy(oldrk, rk, sizeof(rk));for (p 0, i 1; i n; i)rk[sa[i]] cmp(sa[i], sa[i - 1], w) ? p : p;}for (i 1; i n; i) printf(%d , sa[i]);return 0;
}manacher #include bits/stdc.h
using namespace std;
const int N 22000010;
char s[N];
char str[N];
int p[N];//表示以i为中心的最长回文子串长度int init() {int len strlen(s);str[0] , str[1] #;int j 2;for (int i 0; i len; i) str[j] s[i], str[j] #;str[j] \0;
// coutjendl;return j;
}
int manacher() {int ans -1, len init(); int mx 0;//同时记录一个当前延伸最远的回文子串 int id 0;//对称中心 for (int i 1; i len; i) {if (i mx) p[i] min(p[id * 2 - i], mx - i);else p[i] 1;while (str[i p[i]] str[i - p[i]]) p[i];if (p[i] i mx) mx p[i] i, id i;ans max(ans, p[i] - 1);}return ans;
}
int main()
{while(cins){cout manacher()endl;char chgetchar();}return 0;
}
hash
#includebits/stdc.h
using namespace std;
typedef unsigned long long ull;
ull base131;
ull a[10010];
char s[10010];
int n,ans1;
ull hashs(char s[])
{int lenstrlen(s);ull ans0;for(int i0;ilen;i)ansans*base(ull)s[i];return ans0x7fffffff;
}
int main()
{scanf(%d,n);for(int i1;in;i){scanf(%s,s);a[i]hashs(s); couta[]a[i]endl;}sort(a1,an1);for(int i2;in;i){if(a[i]!a[i-1])ans;}printf(%d\n,ans);
}
KMP
#includestdio.h
#includeiostream
#includestring.h
using namespace std ;
const int maxn 1e65;
int Next[maxn];
char str[maxn];
char mo[maxn];
int n1,n2;
void GetNext()
{int i0,j-1;while(in2){if(j-1||mo[i]mo[j]) {i,j,Next[i]j;}else jNext[j];}return ;
}
int kmp()
{int cnt0;int i0,j0;int w;while(in1){if(j-1||str[i]mo[j]) i,j;else jNext[j];if(jn2){wi-n21;return w;// cnt;// jNext[j];//完成一次匹配将j移动到最长的前缀处省略不必要的查找}}return -1;
}
int main()
{int t;scanf(%d,t);while(t--){scanf(%s%s,str,mo);//str是主串 mo是副串 n1strlen(str);n2strlen(mo);Next[0]-1;GetNext();printf(%d\n,kmp());}return 0;
}最大最小表达法
#includebits/stdc.h
using namespace std;
#define N 10005
char str[N];
int Minrp(char *s,int l){int i0,j1,k0,t;//表示从i开始k长度和从j开始k长度的字符串相同//t用来计算相对应位置上那个字典序较大while(il jl kl){int mi,mj;miik;mjjk;if(mil)mi-l;if(mjl)mj-l;// (ik) l ? ik-l : ik// (jk) l ? jk-l : jkt s[mi] - s[mj];if(t0)k;//t为零两数相同 else {if(t0)i ik1;//是最小表达法 是最大表达法 else j jk1;if(ij)j;k 0;}}return i;
}
int main(){int n;int T;scanf(%d,T);while(T--){scanf(%s,str);printf(%d\n,Minrp(str,strlen(str))1);}return 0;
}
数论
约瑟夫环
//从第一个开始报数数到k的将被杀掉
int josepus(int n,int k)
{int r0;for(int i2;in;i) r(rk)%i;return r1; //0~n-1 所以最后结果1
}
//第m个被杀掉的人
int josepus(int n,int m,int k)
{r(k-1)%(n-m1);for(int i2;im;i){r(rk)%(n-mi);}return r1;
}
欧拉函数
线性筛求欧拉函数
//线性筛
/* * Author: lzyws739307453 * Language: C */
#include bits/stdc.h
using namespace std;
const int MAXN 1e6 5;
bool vis[MAXN];
int prime[MAXN], phi[MAXN];
void Euler(int n) {phi[1] 1;int cnt 0;for (int i 2; i n; i) {if (!vis[i]) {prime[cnt] i;phi[i] i - 1;}for (int j 0; j cnt prime[j] n / i; j) {vis[prime[j] * i] true;if (i % prime[j])phi[i * prime[j]] phi[i] * (prime[j] - 1);else {phi[i * prime[j]] phi[i] * prime[j];break;}}}
}
int main() {int n;scanf(%d, n);Euler(n);long long ans 0;for (int i 1; i n; i)ans phi[i];printf(%lld\n, ans);return 0;
}莫比乌斯反演
#include cstdio
#include algorithm
#include cstring
using namespace std;const int N1e55;
int p[N10],check[N10],tot;
int mu[N],sum[N];
int T,n,m,d,ans;void init(){memset(check,1,sizeof check);mu[1]1;for(int i2;iN;i){if (check[i]){p[tot]i;mu[i]-1;}for (int j1;jtot p[j]*iN;j){check[i*p[j]]0;if (i%p[j]0){mu[i*p[j]]0;break; }else mu[i*p[j]]-mu[i];}}for(int i1;iN;i)sum[i]mu[i]sum[i-1]; //维护前缀和
}int calc(int n,int m){ //求[1,n][1,m]区间内互质的(x,y)的对数int ret0;if (nm) swap(n,m);for (int L1,R0;Ln;LR1){Rmin(n/(n/L),m/(m/L)); // 分段ret(sum[R]-sum[L-1])*(n/L)*(m/L);}return ret;
}int main(){init();scanf(%d,T);while (T--){scanf(%d%d%d,n,m,d);anscalc(n/d,m/d);printf(%d\n,ans);}return 0;
}逆序对
归并排序求逆序对
#includebits/stdc.h
#includeiostream
#includealgorithm
#includecstdio
#includecstring
#includestring
#includequeue
#includecmath
#define ll long long
#define DB double
#define inf 214748360000
#define mod 1000000007
using namespace std;
const int N1e590;
int n,a[N*60],b[N*60];
ll ans;//ans为逆序对个数
void merge_sort(int l,int r)
{if(lr) return;int mid(lr)1,i,j,k;il; jmid1; kl;merge_sort(l,mid);merge_sort(mid1,r);while(imid jr){if(a[i]a[j]) b[k]a[i];else ansmid-i1,b[k]a[j]; }while(imid) b[k]a[i];while(jr) b[k]a[j];//当左右子序列填完后剩余的自动后补 memcpy(a,b1,sizeof(b));//for(int zl;zr;z) a[z]b[z];
}
int main()
{scanf(%d,n);for(int i1;in;i) scanf(%d,a[i]);merge_sort(1,n);for(int i1;in;i) printf(%d ,a[i]);coutendl;printf(%lld,ans);return 0;
}素数
线性筛
#includebits/stdc.h
using namespace std;
#define MAXN 100005
#define MAXL 1299710
int prime[MAXN];
int tag[MAXL];
int tot 0;
void Prime(int N){memset(tag,0,sizeof(tag));int cnt0;tag[0]tag[1]1;for(int i 2; iN; i){if(!tag[i]) prime[cnt]i;for(int j0;jcnt prime[j]*iN; j){tag[i*prime[j]] 1;//prime[j]是素数它的倍数也是素数 if(i % prime[j]0)break;//i是某个素数的倍数直接跳出 }}
}
int main()
{int n; Prime(99);for(int i1;i;i){scanf(%d,n);if(tag[n])cout不是素数endl;else cout是素数endl;}return 0;
}欧几里得与扩展欧几里得
欧几里得算法
ll gcd(ll a,ll b)
{return b0?a:gcd(b,a%b);
}
扩展欧几里得算法
#includeiostream
#includecstdio
#includecmathusing namespace std;int exgcd(int a,int b,int x,int y)//扩展欧几里得算法
{if(b0){x1;y0;return a; //到达递归边界开始向上一层返回}int gcdexgcd(b,a%b,x,y);int y1y; //把x y变成上一层的int x1x;yx1-(a/b)*y1;xy1;return gcd; //得到a b的最大公因数
}
逆元
扩展欧几里得
ll exgcd(ll a,ll b,ll x,ll y)//扩展欧几里得算法
{if(b0){x1;y0;return a; //到达递归边界开始向上一层返回}ll gcdexgcd(b,a%b,x,y);ll y1y; //把x y变成上一层的ll x1x;yx1-(a/b)*y1;xy1;return gcd; //得到a b的最大公因数
}
ll inv(ll a,ll mod){ll x,y;ll gcdexgcd(a,mod,x,y);if(gcd!1)return -1;else return (xmod)%mod;
}
费马小定理欧拉定理
ll poww(ll a,ll b,ll mod){ll ans1;ll basea;while(b){if(b1)ansans*base%mod;basebase*base%mod;b1;}return ans%mod;
}
ll inv(ll a,ll mod){return poww(a,mod-2,mod);
}
递推求逆元
long long inv[maxn]; void init(long long n,long long p) { inv[1]1; for(int i2;in;i) { inv[i]((p-p/i)*inv[p%i]%p); } }
__int128高精度运算
使用__int128可以实现高精度运算但是这种大整数无法使用函数printf输出结果所以需要手写输出
#include bits/stdc.h
using namespace std;
inline __int128 read()
{__int128 x0,f1;char chgetchar();while(ch0||ch9){if(ch-)f-1;chgetchar();}while(ch0ch9){xx*10ch-0;chgetchar();}return x*f;
}inline void write(__int128 x)
{if(x0){putchar(-);x-x;}if(x9)write(x/10);putchar(x%100);
}int main()
{__int128 a read();__int128 b read();write(a b);return 0;
}
唯一分解定理
博客讲解
一个数n肯定能被分解成 np1a1 * p2a2 . . .*pnan prime_fac[cnt]存放的底数都是质数 prime_index[cnt]存放的指数也就是每个对数对应的指数
int prime_fac[N],cnt0,sum;
int prime_index[N];
void fact(int n){for(int i2;i*in;i){if(n%i0){cnt;prime_fac[cnt]i;prime_index[cnt]0;}while(n%i0){n/i;prime_index[cnt];sum;}}if(n!1){cnt;prime_fac[cnt]n;//底数 prime_index[cnt]1;//指数sum;}
}数据结构
树链剖分
#includealgorithm
#includeiostream
#includecstdlib
#includecstring
#includecstdio
#define Rint register int
#define mem(a,b) memset(a,(b),sizeof(a))
#define Temp templatetypename T
using namespace std;
typedef long long LL;
Temp inline void read(T x){x0;T w1,chgetchar();while(!isdigit(ch)ch!-)chgetchar();if(ch-)w-1,chgetchar();while(isdigit(ch))x(x3)(x1)(ch^0),chgetchar();xx*w;
}#define mid ((lr)1)
#define lson rt1,l,mid
#define rson rt1|1,mid1,r
#define len (r-l1)const int maxn20000010;
int n,m,r,mod;
//见题意
int e,beg[maxn],nex[maxn],to[maxn],w[maxn],wt[maxn];
//链式前向星数组w[]、wt[]初始点权数组
int a[maxn2],laz[maxn2];
//线段树数组、lazy操作
int son[maxn],id[maxn],fa[maxn],cnt,dep[maxn],siz[maxn],top[maxn];
//son[]重儿子编号,id[]新编号,fa[]父亲节点,
//cnt dfs_clock/dfs序,dep[]深度,siz[]子树大小,top[]当前链顶端节点
int res0;
//查询答案 inline void add(int x,int y){//链式前向星加边 to[e]y;nex[e]beg[x];beg[x]e;
}
//-------------------------------------- 以下为线段树
inline void pushdown(int rt,int lenn){laz[rt1]laz[rt];laz[rt1|1]laz[rt];a[rt1]laz[rt]*(lenn-(lenn1));a[rt1|1]laz[rt]*(lenn1);a[rt1]%mod;a[rt1|1]%mod;laz[rt]0;
}inline void build(int rt,int l,int r){if(lr){a[rt]wt[l];if(a[rt]mod)a[rt]%mod;return;}build(lson);build(rson);a[rt](a[rt1]a[rt1|1])%mod;
}inline void query(int rt,int l,int r,int L,int R){if(LlrR){resa[rt];res%mod;return;}else{if(laz[rt])pushdown(rt,len);if(Lmid)query(lson,L,R);if(Rmid)query(rson,L,R);}
}inline void update(int rt,int l,int r,int L,int R,int k){if(LlrR){laz[rt]k;a[rt]k*len;}else{if(laz[rt])pushdown(rt,len);if(Lmid)update(lson,L,R,k);if(Rmid)update(rson,L,R,k);a[rt](a[rt1]a[rt1|1])%mod;}
}
//---------------------------------以上为线段树
inline int qRange(int x,int y){int ans0;while(top[x]!top[y]){//当两个点不在同一条链上 if(dep[top[x]]dep[top[y]])swap(x,y);//把x点改为所在链顶端的深度更深的那个点res0;query(1,1,n,id[top[x]],id[x]);//ans加上x点到x所在链顶端 这一段区间的点权和ansres;ans%mod;//按题意取模 xfa[top[x]];//把x跳到x所在链顶端的那个点的上面一个点}//直到两个点处于一条链上if(dep[x]dep[y])swap(x,y);//把x点深度更深的那个点res0;query(1,1,n,id[x],id[y]);//这时再加上此时两个点的区间和即可ansres;return ans%mod;
}inline void updRange(int x,int y,int k){//同上 k%mod;while(top[x]!top[y]){if(dep[top[x]]dep[top[y]])swap(x,y);update(1,1,n,id[top[x]],id[x],k);xfa[top[x]];}if(dep[x]dep[y])swap(x,y);update(1,1,n,id[x],id[y],k);
}inline int qSon(int x){res0;query(1,1,n,id[x],id[x]siz[x]-1);//子树区间右端点为id[x]siz[x]-1 return res;
}inline void updSon(int x,int k){//同上 update(1,1,n,id[x],id[x]siz[x]-1,k);
}inline void dfs1(int x,int f,int deep){//x当前节点f父亲deep深度 dep[x]deep;//标记每个点的深度 fa[x]f;//标记每个点的父亲 siz[x]1;//标记每个非叶子节点的子树大小 int maxson-1;//记录重儿子的儿子数 for(Rint ibeg[x];i;inex[i]){int yto[i];if(yf)continue;//若为父亲则continue dfs1(y,x,deep1);//dfs其儿子 siz[x]siz[y];//把它的儿子数加到它身上 if(siz[y]maxson)son[x]y,maxsonsiz[y];//标记每个非叶子节点的重儿子编号 }
}inline void dfs2(int x,int topf){//x当前节点topf当前链的最顶端的节点 id[x]cnt;//标记每个点的新编号 wt[cnt]w[x];//把每个点的初始值赋到新编号上来 top[x]topf;//这个点所在链的顶端 if(!son[x])return;//如果没有儿子则返回 dfs2(son[x],topf);//按先处理重儿子再处理轻儿子的顺序递归处理 for(Rint ibeg[x];i;inex[i]){int yto[i];if(yfa[x]||yson[x])continue;dfs2(y,y);//对于每一个轻儿子都有一条从它自己开始的链 }
}int main(){read(n);read(m);read(r);read(mod);for(Rint i1;in;i)read(w[i]);for(Rint i1;in;i){int a,b;read(a);read(b);add(a,b);add(b,a);}dfs1(r,0,1);dfs2(r,r);build(1,1,n);while(m--){int k,x,y,z;read(k);if(k1){read(x);read(y);read(z);updRange(x,y,z);//将树从 x 到 y 结点最短路径上所有节点的值都加上 z}else if(k2){//求树从 x 到 y 结点最短路径上所有节点的值之和。 read(x);read(y);printf(%d\n,qRange(x,y));}else if(k3){//以 x 为根节点的子树内所有节点值都加上 z。 read(x);read(y);updSon(x,y);}else{read(x);printf(%d\n,qSon(x));//求以 xx 为根节点的子树内所有节点值之和 }}
}字典树
#includecstdio
#includeiostream
#includecstring
using namespace std;
const int MAX_NODE 1000000 10;
const int CHARSET 26;
int trie[MAX_NODE][CHARSET] {0};
int color[MAX_NODE] {0};
int k 1;void insert(char *w){int len strlen(w);int p 0;for(int i0; ilen; i){int c w[i] - a;if(!trie[p][c]){trie[p][c] k;k;}p trie[p][c];}color[p] 1;
}int search(char *s){int len strlen(s);int p 0;for(int i0; ilen; i){int c s[i] - a;if(!trie[p][c]) return 0;p trie[p][c];}return color[p] 1;
}int main(){int t,q;char s[20];scanf(%d%d, t,q);while(t--){scanf(%s, s);insert(s);}while(q--){scanf(%s, s);if(search(s)) printf(YES\n);else printf(NO\n);}return 0;
}树状数组
#include iostream
#include cstdio
#include cstdlib
#include cstring
#include cmath
#include algorithm
#include queue
#include string
#include vector
#define For(a,b) for(int a0;ab;a)
#define mem(a,b) memset(a,b,sizeof(a))
#define _mem(a,b) memset(a,0,(b1)2)
#define lowbit(a) ((a)-(a))
using namespace std;
typedef long long ll;
const int maxn 5*1e45;
const int INF 0x3f3f3f3f;
int c[maxn];
void update(int x,int y,int n){for(int ix;in;ilowbit(i))c[i] y;
}
int getsum(int x){int ans 0;for(int ix;i;i-lowbit(i))ans c[i];return ans;
}
int main()
{int t;int n;int x,y,z;string s;cin t ;for(int j1;jt;j){scanf(%d,n);_mem(c,n);//初始化数组中前n1个数为0for(int i1;in;i){scanf(%d,z);update(i,z,n);}cout Case j:endl;while(1){cin s;if(s[0] E)break;scanf(%d%d,x,y);if(s[0] Q)cout getsum(y)-getsum(x-1)endl;else if(s[0] A)update(x,y,n);elseupdate(x,-y,n);}}return 0;
}二维树状数组
单点修改区域求值
#includebits/stdc.h
using namespace std;
const int maxn1e36;
int c[maxn][maxn];
int a[maxn][maxn];
int n,m;
int lowbit(int x)
{return x(-x);
}
void add(int x,int y,int z)
{for(int ix;in;ilowbit(i)){for(int jy;jn;jlowbit(j)){c[i][j]z;}}
}
int ask(int x,int y)
{int ans0;for(int ix;i;i-lowbit(i)){for(int jy;j;j-lowbit(j)){ansc[i][j];}}return ans;
}
int main()
{cinnm;for(int i1;in;i){for(int j1;jn;j){cina[i][j];add(i,j,a[i][j]);}}while(m--){int f;cinf;if(f1){int x1,y1;cinx1y1;if(a[x1][y1])add(x1,y1,-1);else add(x1,y1,1);a[x1][y1]^1;}else {int x1,y1,x2,y2;cinx1y1x2y2;int ansask(x2,y2)-ask(x1-1,y2)-ask(x2,y1-1)ask(x1-1,y1-1);coutansendl;}}return 0;
}区域修改单点求值
const int MAX 1010;
int n, cnt[MAX][MAX];int lowbit(int x){return x (-x);
}
void add(int x, int y, int val){for(int i x; i n; i lowbit(i))for(int j y; j n; j lowbit(j))cnt[i][j] val;
}
int sum(int x, int y){int res 0;for(int i x; i 0; i - lowbit(i))for(int j y; j 0; j - lowbit(j))res cnt[i][j];return res;
}int main()
{int t, m, x1, y1, x2, y2;char op[10];cin t;while(t--){scanf(%d%d, n, m);memset(cnt, 0, sizeof(cnt));while(m--){scanf(%s%d%d, op, x1, y1);if(op[0] C){scanf(%d%d, x2, y2);add(x1, y1, 1);add(x1, y21, 1);add(x21, y1, 1);add(x21, y21, 1);}else{printf(%d\n, sum(x1,y1) % 2);}}printf(\n);}
}int sum(int x,int y)
{int ret 0;int i,j;for(i x;i1;i-lowbit(i)){for(j y;j1;j-lowbit(j)){retc[i][j];}}return ret;
}void add(int x,int y)
{int i,j;for(i x;in;ilowbit(i)){for(j y;jn;jlowbit(j)){c[i][j];}}
}int main()
{int i,j,x,y,ans,t;int x1,x2,y1,y2;char op[10];scanf(%d,t);while(t--){scanf(%d%d,n,m);MEM(c,0);MEM(a,0);while(m--){scanf(%s,op);if(op[0]C){scanf(%d%d%d%d,x1,y1,x2,y2);x1,y1,x2,y2;add(x2,y2);add(x1-1,y1-1);add(x2,y1-1);add(x1-1,y2);}else{scanf(%d%d,x1,y1);x2 x1,y2 y1;x1,y1,x2,y2;printf(%d\n,sum(x1,y1));}}printf(\n);}return 0;
}
线段树
区间查询单点修改
inline int search(int i,int l,int r){if(tree[i].lltree[i].rr)return tree[i].sum;if(tree[i].rl||tree[i].lr)return 0;int sum0;if(tree[i*2].rl)sumsearch(i*2,l,r);if(tree[i*21].lr)sumsearch(i*21,l,r);return sum;
}
inline void add(int i,int dis,int k)
{if(tree[i].ltree[i].r){tree[i].sumk;return;}if(distree[i*2].r)add(i*2,dis,k);else add(i*21,dis,k);tree[i].sumtree[i*2].sumtree[i*21].sum;return ;
}
区间修改单点查询
inline void add(int i,int l,int r,int k)
{if(tree[i].lltree[i].rr){tree[i].numk;return;}if(tree[i*2].rl)add(i*2,l,r,k);if(tree[i*21].lr)add(i*21,l,r,k);
}
void search(int i,int dis){anstree[i].num;if(distree[i*2].r)search(i*2,dis);if(distree[i*21].l)search(i*21,dis);
}
基础模板 区间求和单点修改
#includeiostream
#includecstdio
#define MAXN 1000001
#define ll long long
using namespace std;
unsigned ll n,m,a[MAXN],ans[MAXN2],tag[MAXN2];
inline ll ls(ll x)
{return x1;
}
inline ll rs(ll x)
{return x1|1;
}
void scan()
{cinnm;for(ll i1;in;i)scanf(%lld,a[i]);
}
inline void push_up(ll p)
{ans[p]ans[ls(p)]ans[rs(p)];
}
void build(ll p,ll l,ll r)
{tag[p]0;if(lr){ans[p]a[l];return ;}ll mid(lr)1;build(ls(p),l,mid);build(rs(p),mid1,r);push_up(p);
}
inline void f(ll p,ll l,ll r,ll k)
{tag[p]tag[p]k;ans[p]ans[p]k*(r-l1);
}
inline void push_down(ll p,ll l,ll r)
{ll mid(lr)1;f(ls(p),l,mid,tag[p]);f(rs(p),mid1,r,tag[p]);tag[p]0;
}
inline void update(ll nl,ll nr,ll l,ll r,ll p,ll k)
{if(nllrnr){ans[p]k*(r-l1);tag[p]k;return ;}push_down(p,l,r);ll mid(lr)1;if(nlmid)update(nl,nr,l,mid,ls(p),k);if(nrmid) update(nl,nr,mid1,r,rs(p),k);push_up(p);
}
ll query(ll q_x,ll q_y,ll l,ll r,ll p)
{ll res0;if(q_xlrq_y)return ans[p];ll mid(lr)1;push_down(p,l,r);if(q_xmid)resquery(q_x,q_y,l,mid,ls(p));if(q_ymid) resquery(q_x,q_y,mid1,r,rs(p));return res;
}
int main()
{ll a1,b,c,d,e,f;scan();build(1,1,n);while(m--){scanf(%lld,a1);switch(a1){case 1:{scanf(%lld%lld%lld,b,c,d);update(b,c,1,n,1,d);break;}case 2:{scanf(%lld%lld,e,f);printf(%lld\n,query(e,f,1,n,1));break;}}}return 0;
}区间求和单点乘数单点添加
#includebits/stdc.h
#define ll long long
using namespace std;
int n,m,a[1000005],mod;
struct node{ll sum,l,r,mu,add;
}t[1000005];
ll read(){ll x0;char chgetchar();while(ch0||ch9)chgetchar();while(ch0ch9)x(x1)(x3)(ch^48),chgetchar();return x;
}
void build(ll p,ll l,ll r){t[p].ll,t[p].rr;t[p].mu1;if(lr){t[p].suma[l]%mod;return ;}ll mid(lr)1;build(p*2,l,mid);build(p*21,mid1,r);t[p].sum(t[p*2].sumt[p*21].sum)%mod;
}
void spread(ll p){t[p*2].sum(ll)(t[p].mu*t[p*2].sum((t[p*2].r-t[p*2].l1)*t[p].add)%mod)%mod;t[p*21].sum(ll)(t[p].mu*t[p*21].sum(t[p].add*(t[p*21].r-t[p*21].l1))%mod)%mod;//add已经乘过mu啦t[p*2].mu(ll)(t[p*2].mu*t[p].mu)%mod;t[p*21].mu(ll)(t[p*21].mu*t[p].mu)%mod;t[p*2].add(ll)(t[p*2].add*t[p].mut[p].add)%mod;t[p*21].add(ll)(t[p*21].add*t[p].mut[p].add)%mod;t[p].mu1,t[p].add0;
}
void add(ll p,ll l,ll r,ll k){if(t[p].llt[p].rr){t[p].add(t[p].addk)%mod;t[p].sum(ll)(t[p].sumk*(t[p].r-t[p].l1))%mod;//只要加上增加的就好return ;}spread(p);t[p].sum(t[p*2].sumt[p*21].sum)%mod;ll mid(t[p].lt[p].r)1;if(lmid)add(p*2,l,r,k);if(midr)add(p*21,l,r,k);t[p].sum(t[p*2].sumt[p*21].sum)%mod;}
void mu(ll p,ll l,ll r,ll k){if(t[p].llt[p].rr){t[p].add(t[p].add*k)%mod;//比较重要的一步,add要在这里乘上k,因为后面可能要加其他的数而那些数其实是不用乘k的t[p].mu(t[p].mu*k)%mod;t[p].sum(t[p].sum*k)%mod;return ;}spread(p);t[p].sumt[p*2].sumt[p*21].sum;ll mid(t[p].lt[p].r)1;if(lmid)mu(p*2,l,r,k);if(midr)mu(p*21,l,r,k);t[p].sum(t[p*2].sumt[p*21].sum)%mod;
}
ll ask(ll p,ll l,ll r){if(t[p].llt[p].rr){return t[p].sum;}spread(p);ll val0;ll mid(t[p].lt[p].r)1;if(lmid)val(valask(p*2,l,r))%mod;if(midr)val(valask(p*21,l,r))%mod;return val;
}
int main(){cinnmmod;for(int i1;in;i){a[i]read();}build(1,1,n);for(int i1;im;i){int tyread();if(ty1){ll cnread(),cmread(),cwread();mu(1,cn,cm,cw);}else if(ty2){ll cnread(),cmread(),cwread();add(1,cn,cm,cw);}else {ll cnread(),cmread();coutask(1,cn,cm)endl;}}
}权值线段树
// luogu-judger-enable-o2
//#pragma comment(linker, /STACK:1024000000,1024000000)#includestdio.h
#includestring.h
#includemath.h
#includetime.h#includemap
#includeset
#includedeque
#includequeue
#includestack
#includebitset
#includestring
#includefstream
#includeiostream
#includealgorithm
using namespace std;#define ll long long
#define Pair pairll,int
//#define max(a,b) (a)(b)?(a):(b)
//#define min(a,b) (a)(b)?(a):(b)
#define clean(a,b) memset(a,b,sizeof(a))// 水印
//std::ios::sync_with_stdio(false);
// register
const int MAXN2e510;
const int INF320x3f3f3f3f;
const ll INF640x3f3f3f3f3f3f3f3f;
const ll mod1e97;
const double EPS1.0e-8;
const double PIacos(-1.0);ll Tree[MAXN2];
ll a[MAXN],sum[MAXN];
ll n,t;int get_r(ll res){int l1,rn,mid;while(lr){//find the last r to sum[l-1]sum[r]-t ressum[r]mid(lr)1;if(ressum[mid]) lmid1;else rmid-1;}return r;
}
int get_l(ll res){int l1,rn,mid;while(lr){mid(lr)1;if(ressum[mid]) return mid;else if(ressum[mid]) lmid1;else rmid-1;}
}
void Update(int l,int r,int x,int oper,int rt){//修改一个点 if(lr){Tree[rt]oper;return ;}int mid(lr)1;if(xmid) Update(l,mid,x,oper,rt1);else Update(mid1,r,x,oper,rt1|1);Tree[rt]Tree[rt1]Tree[rt1|1];
}
int Query(int ql,int qr,int l,int r,int rt){if(qr0) return 0;if(lqlrqr){return Tree[rt];}int mid(lr)1;int ans0;if(qlmid) ansQuery(ql,qr,l,mid,rt1);if(qrmid) ansQuery(ql,qr,mid1,r,rt1|1);return ans;
}
int main(){while(~scanf(%lld%lld,n,t)){clean(Tree,0);for(int i1;in;i){scanf(%lld,a[i]);sum[i]sum[i-1]a[i];}sort(sum1,sum1n);for(int i1;in;i){sum[i]sum[i]-t;}sort(sum1,sum1n);for(int i1;in;i){Update(1,n,i,1,1);}ll ans0,res0;for(int i1;in;i){int rget_r(res);
// coutr : ;ansQuery(1,r,1,n,1);
// coutans ;resa[i];int lget_l(res-t);Update(1,n,l,-1,1);}printf(%lld\n,ans);}
}
/*
*/主席树
#includecstdio
#includecstring
#includeiostream
#includealgorithm
#includecmath
#includecctype
#includevector
#includemap
#includequeue
#define rep(i, x, y) for (int i (x); i (y); i )
#define down(i, x, y) for (int i (x); i (y); i --)
#define mid (lr)/2
#define lc o1
#define rc o1|1
#define pb push_back
#define mp make_pair
#define Pair pairint, int
#define F first
#define S second
#define B begin()
#define E end()
using namespace std;
typedef long long LL;
//headconst int N 100010, LOG 20;
int n, m, q, tot 0;
int a[N], b[N];
int T[N], sum[N*LOG], L[N*LOG], R[N*LOG];inline int build(int l, int r)
{int rt tot;if (l r){L[rt] build(l, mid);R[rt] build(mid1, r);}return rt;
}inline int update(int pre, int l, int r, int x)
{int rt tot;L[rt] L[pre]; R[rt] R[pre]; sum[rt] sum[pre] 1; if (l r){if (x mid) L[rt] update(L[pre], l, mid, x);else R[rt] update(R[pre], mid1, r, x);}return rt;
}inline int query(int u, int v, int l, int r, int k)
{if (l r) return l;int x sum[L[v]] - sum[L[u]];if (x k) return query(L[u], L[v], l, mid, k);else return query(R[u], R[v], mid1, r, k-x);
}int main()
{int Test; scanf(%d, Test);while (Test --){tot 0;memset(T, 0, sizeof T); memset(sum, 0, sizeof sum);memset(L, 0, sizeof L); memset(R, 0, sizeof R);scanf(%d%d, n, q);rep(i, 1, n) scanf(%d, a[i]), b[i] a[i];sort(b1, b1n);m unique(b1, b1n)-b-1;T[0] build(1, m);rep(i, 1, n){a[i] lower_bound(b1, b1m, a[i]) - b;T[i] update(T[i-1], 1, m, a[i]);}while (q --){int x, y, z; scanf(%d%d%d, x, y, z);int p query(T[x-1], T[y], 1, m, z);printf(%d\n, b[p]);}}return 0;
}#include bits/stdc.h
#define maxn 200010
using namespace std;
int a[maxn], b[maxn], n, m, q, p, sz;
int lc[maxn 5], rc[maxn 5], sum[maxn 5], rt[maxn 5];
//空间要注意inline int read(){int s 0, w 1;char c getchar();for (; !isdigit(c); c getchar()) if (c -) w -1;for (; isdigit(c); c getchar()) s (s 1) (s 3) (c ^ 48);return s * w;
}void build(int rt, int l, int r){rt sz, sum[rt] 0;if (l r) return;int mid (l r) 1;build(lc[rt], l, mid); build(rc[rt], mid 1, r);
}int update(int o, int l, int r){int oo sz;lc[oo] lc[o], rc[oo] rc[o], sum[oo] sum[o] 1;if (l r) return oo;int mid (l r) 1;if (mid p) lc[oo] update(lc[oo], l, mid); else rc[oo] update(rc[oo], mid 1, r);return oo;
}int query(int u, int v, int l, int r, int k){int mid (l r) 1, x sum[lc[v]] - sum[lc[u]];if (l r) return l;if (x k) return query(lc[u], lc[v], l, mid, k); else return query(rc[u], rc[v], mid 1, r, k - x);
}int main(){n read(), m read();for (int i 1; i n; i) a[i] read(), b[i] a[i];sort(b 1, b 1 n);q unique(b 1, b 1 n) - b - 1;build(rt[0], 1, q);for (int i 1; i n; i){p lower_bound(b 1, b 1 q, a[i]) - b;rt[i] update(rt[i - 1], 1, q);} while (m--){int l read(), r read(), k read();printf(%d\n, b[query(rt[l - 1], rt[r], 1, q, k)]);}return 0;
}
单调栈
博客讲解
typedef pairint, intpa;int n, m;
int a[2005][2005];
pa f[2005];
stackpas;int main() {while(~scanf(%d%d, n, m)){for(int i 1; i n; i){for(int j 1; j m; j){scanf(%d, a[i][j]);if (a[i][j]) a[i][j] a[i-1][j];//求连续的高度 }}int ans 0;pa v;for(int i 1; i n; i){for(int j 1; j m; j){if (s.empty() !a[i][j]) continue;if (s.empty() || s.top().second a[i][j])//当高度小于时 s.push(make_pair(j, a[i][j]));else {while(!s.empty() s.top().second a[i][j]){v s.top();s.pop();int area (j-v.first)*v.second;//求面积 if (area ans) ans area; }s.push(make_pair(v.first, a[i][j]));}}}printf(%d\n, ans);}return 0;
}
图论
拓扑排序
/*hdu1285--采用邻接表记录两者之间的关系*/
#includecstdio
#includecstring
int head[510];
int indegree[510];
int queue[510];
int num;
struct stu{int to,next;
}edge[2510];
void inin(){//初始化memset(indegree,0,sizeof(indegree));memset(head,-1,sizeof(head));num0;
}
void add(int a,int b){//添加边stu E{b,head[a]};edge[num]E;head[a]num;indegree[b];
}
void topo(int n){int i,j,id,t0;for(j1;jn;j){for(i1;in;i){if(indegree[i]0){idi;break;}}queue[t]id;indegree[id]-1;for(ihead[id];i!-1;iedge[i].next){int kedge[i].to;indegree[k]--;}}printf(%d,queue[0]);//输出拓扑序列for(i1;in;i){printf( %d,queue[i]);}printf(\n);
}
int main(){int n,m,i,j,a,b;while(scanf(%d%d,n,m)!EOF){inin();for(i1;im;i){scanf(%d%d,a,b);add(a,b);}topo(n);}return 0;
}tarjan
#includeiostream //输出所有强连通分量
#includecstdio
#includecstring
#includealgorithm
using namespace std;int n,m,x,y,top0,cnt0,t,col;
int ans1-1,ans2-1,ans3-1;
int d[200020];
int a[200020];
int c[200020];
int f[200020];
int dfn[200020];
int low[200020];
int stack[200020];bool v[200020];struct edge{int u;int v;int w;int next;
}e[1000020];void Add(int u,int v,int w)
{top;e[top].uu;e[top].vv;e[top].ww;e[top].nextf[u];f[u]top;
}int read()
{int x0;int k1;char cgetchar();while(c9||c0){if(c-) k-1;cgetchar();}while(c0c9)xx*10c-0,cgetchar();return x*k;
}void tarjan(int now)
{dfn[now]low[now]cnt;//初始化stack[t]now;//入栈操作v[now]1;//v[]代表该点是否已入栈for(int if[now];i!-1;ie[i].next)//邻接表存图if(!dfn[e[i].v]) //判断该点是否被搜索过{tarjan(e[i].v);low[now]min(low[now],low[e[i].v]); //回溯时更新low[ ]取最小值}else if(v[e[i].v])low[now]min(low[now],dfn[e[i].v]);
//一旦遇到已入栈的点就将该点作为连通量的根
//这里用dfn[e[i].v]更新的原因是这个点可能
//已经在另一个强连通分量中了但暂时尚未出栈所//以now不一定能到达low[e[i].v]但一定能到达//dfn[e[i].v].if(dfn[now]low[now]){int cur;do{curstack[t--];v[cur]false; //不要忘记出栈}while(now!cur);printf(now%d\n,now);}
}
int main()
{nread();mread();memset(f,-1,sizeof f);for(int i1;in;i)a[i]read();for(int i1;im;i){xread();yread();Add(x,y,0);}for(int i1;in;i)if(!dfn[i]) tarjan(i);return 0;
}求割点
#include iostream
#include cstdio
#include cstdlib
#include cmath
#include cstring
#include algorithm
#include vector
#include stack
using namespace std;
const int MAXN 2000010;
int N, M;
vector int E[MAXN], cutp;
int dfn[MAXN], low[MAXN], timer;
void dfs(int u, int fa){dfn[u] low[u] timer;int son 0;bool f false;for(int i0;iE[u].size();i){int v E[u][i];if(v fa) continue;if(!dfn[v]){son;dfs(v, u);if(dfn[u] low[v]) f true;low[u] min(low[u], low[v]);}else low[u] min(low[u], dfn[v]);}if((!fa son1) || (fa f)) cutp.push_back(u);
}
void Tarjan(){for(int i1;iN;i){if(!dfn[i]) dfs(i, 0);}
}
int main(){scanf(%d%d, N, M);while(M--){int from, to;scanf(%d%d, from, to);E[from].push_back(to);E[to].push_back(from);}Tarjan();printf(%d\n, (int)cutp.size());sort(cutp.begin(), cutp.end());for(int i0;icutp.size();i)printf(icutp.size()-1?%d :%d\n, cutp[i]);return 0;
}二分图匹配–匈牙利算法
#includeiostream
#includecstring
using namespace std;
const int maxn 3;
int n maxn, m maxn;
int Map[maxn][maxn];//map[i][j]1表示X部的i和Y部的j存在路径,是否可以匹配
int cx[maxn], cy[maxn];
bool vis[maxn];
//cx[i]表示X部i点匹配的Y部顶点的编号
//cy[i]表示Y部i点匹配的X部顶点的编号bool dfs(int u)//dfs进入的都是X部的点
{for (int v 0; v n; v)//枚举Y部的点判断X部的u和Y部的v是否存在路径{//如果存在路径并且还没被标记加入增广路if (Map[u][v] !vis[v])//vis数组只标记Y组{//标记加入增广路vis[v] 1;//如果Y部的点v还未被匹配//或者已经被匹配了但是可以从v点原来匹配的cy[v]找到一条增广路//说明这条路就可是一个正确的匹配//因为递归第一次进入dfs时u是未匹配的//如果v还没有匹配对象即和它相连的所有边都不在已经选择的匹配边集合MM\in E中这时就找到了u-v增广路径//如果v已经有匹配对象了那么u-v是一条未选择的边//而v-cy[v] \in M 则是一条已经选择的边, dfs(cy[v])从cy[v]开始搜索增广路径//如果新的v没有匹配对象那么u-v-cy[v]-v就是一条增广路径//如果v已经有匹配对象了那么根据匹配是唯一的//cy[v]-v一定不在已经选择的边中(和cy[v]-v冲突)//u-v-cy[v]-v-cy[v]符合增广路径对边顺序的要求继续利用dfs(cy[v])搜索u-v-cy[v]-v-cy[v]-下面的点//当搜索到增广链时如u-v-cy[v]-v,那么经过递归的匹配调整和return 1进行匹配增广操作假设dfs0 是main调用的dfs算法dfs1是dfs0调用的dfs算法//在dfs1中进行cy[v]-v的匹配因为dfs1返回1因此在dfs0中进行u-v的匹配匹配增广操作的结果是{cy[v]-v}-{u-v,cy[v]-v}//如果在一个dfs(k)自调用的dfs(k1)中遍历所有的v(k1),要么已经有匹配点了要么和输入u(k1)没有连接可能这时搜索终止说明不存在经过u(k1)的增广链返回0//而在main调用的dfs(0)中调用的dfs(1)返回的都是0而且v都是已经有匹配了那么不存在从该点出发的增广链那么就该点就不在最大匹配当中//为什么找不到增广链就不在最大匹配当中呢感觉可以用反证法证明博客中下面内容可能有更新这方面的思考if (cy[v] -1 || dfs(cy[v])){cx[u] v;//可以匹配进行匹配cy[v] u;return 1;}}}return 0;//不能匹配
}
int maxmatch()//匈牙利算法主函数
{int ans 0;//匹配清空全部置为-1memset(cx, -1, sizeof(cx));memset(cy, -1, sizeof(cy));for (int i 0; i n; i){if (cx[i] -1)//如果X部的i还未匹配{memset(vis, 0, sizeof(vis));//每次找增广路的时候清空visans dfs(i);}}return ans;
}int main()
{//输入匹配的两个点集合的数量cin n m;//输入两个点集合成员间的匹配可能int x, y;for (int i 0; i m; i){cin x y;Map[x][y] 1;}//执行匈牙利算法输出最大匹配cout maxmatch() endl;return 0;
}
最优匹配
#includeiostream
#includecstdio
#includecstring
#includealgorithm
using namespace std;
const int inf 0x3f3f3f3f;
const int maxn 300 10;
int sx[maxn], sy[maxn], vx[maxn], vy[maxn], match[maxn];
int money[maxn][maxn], slack[maxn];
int n;
void chushihua()
{memset(sy, 0, sizeof(sy));for(int i 1; i n; i){sx[i] 1;for(int j 1; j n; j){scanf(%d, money[i][j]);sx[i] max(sx[i], money[i][j]);}}
}
bool dfs(int x)
{vx[x] true;for(int i 1; i n; i){int xx sx[x] sy[i] - money[x][i];if(!vy[i] !xx){vy[i] true;if(match[i]-1 || dfs(match[i])){match[i] x;return true;}}else if(slack[i] xx)slack[i] xx;}return false;
}
void bestmatch()
{for(int i 1; i n; i){while(1){memset(vx, false, sizeof(vx));memset(vy, false, sizeof(vy));memset(slack, 0x3f, sizeof(slack));if(dfs(i))break;int dd inf;for(int i 1; i n; i)if(!vy[i] ddslack[i])dd slack[i];for(int i 1; i n; i){if(vx[i])sx[i] - dd;if(vy[i])sy[i] dd;}}}
}
int main()
{while(~scanf(%d, n)){memset(match, -1, sizeof(match));chushihua();bestmatch();int sum 0;for(int i 1; i n; i)sum money[match[i]][i];printf(%d\n, sum);}return 0;
}网络流问题
Dinic
#includeiostream
#includecstdio
#includecstring
#includealgorithm
#includequeue
#define maxn 1000001
#define INF 19260817
using namespace std;
int cnt,cost[maxn],from[maxn],to[maxn],Next[maxn],head[maxn];
int level[maxn];
queueintq;
int S,T,n,m;
void add(int x,int y,int z){ //建边cnt;cost[cnt]z;from[cnt]x;to[cnt]y;Next[cnt]head[x];head[x]cnt;
}
bool bfs(){ //bfs分层memset(level,-1,sizeof(level));level[S]0;q.push(S);while(!q.empty()){int uq.front();q.pop();for(int ihead[u];i!-1;iNext[i]){int vto[i];if(cost[i]!0level[v]-1){ //如果容量是0||已被更新就不更新了level[v]level[u]1;q.push(v);}}}if(level[T]!-1)return true; //如果流不动了就结束dinicreturn false;
}
int dfs(int u,int flow){ //dfs找最大流if(uT)return flow;int retflow; //记录初始流量for(int ihead[u];i!-1;iNext[i]){if(ret0)break; //如果已经没流了就退出int vto[i];if(cost[i]!0level[u]1level[v]){int kdfs(v,min(cost[i],ret)); //把能流的都给下一个点ret-k;cost[i]-k;cost[i^1]k; //边权更新剩余流量更新}}return flow-ret; //返回流出的流量
}
int dinic(){int ans0;while(bfs()true){ansdfs(S,INF); //累加最大流}return ans;
}
int main(){cnt1;memset(head,-1,sizeof(head));scanf(%d%d%d%d,n,m,S,T);for(int i1;im;i){int x,y,z;scanf(%d%d%d,x,y,z);add(x,y,z);add(y,x,0); //EK一样建边}printf(%d,dinic());
}
//dinic时间复杂度:O(n^2 m).KM算法
#includeiostream
#includecstdio
#includecstringusing namespace std;const int N310;
const int INF0x3f3f3f3f;int n,nx,ny;
int linker[N],lx[N],ly[N],slack[N]; //lx,ly为顶标nx,ny分别为x点集y点集的个数
int visx[N],visy[N],w[N][N];int DFS(int x){visx[x]1;for(int y1;yny;y){if(visy[y])continue;int tmplx[x]ly[y]-w[x][y];if(tmp0){visy[y]1;if(linker[y]-1 || DFS(linker[y])){linker[y]x;return 1;}}else if(slack[y]tmp){ //不在相等子图中slack 取最小的slack[y]tmp;}}return 0;
}int KM(){int i,j;memset(linker,-1,sizeof(linker));memset(ly,0,sizeof(ly));for(i1;inx;i) //lx初始化为与它关联边中最大的for(j1,lx[i]-INF;jny;j)if(w[i][j]lx[i])lx[i]w[i][j];for(int x1;xnx;x){for(i1;iny;i)slack[i]INF;while(1){memset(visx,0,sizeof(visx));memset(visy,0,sizeof(visy));if(DFS(x)) //若成功找到了增广轨则该点增广完成进入下一个点的增广break; //若失败没有找到增广轨则需要改变一些点的标号使得图中可行边的数量增加。//方法为将所有在增广轨中就是在增广过程中遍历到的X方点的标号全部减去一个常数d//所有在增广轨中的Y方点的标号全部加上一个常数dint dINF;for(i1;iny;i)if(!visy[i] dslack[i])dslack[i];for(i1;inx;i)if(visx[i])lx[i]-d;for(i1;iny;i) //修改顶标后要把所有不在交错树中的Y顶点的slack值都减去dif(visy[i])ly[i]d;elseslack[i]-d;}}int res0;for(i1;iny;i)if(linker[i]!-1)resw[linker[i]][i];return res;
}int main(){//freopen(input.txt,r,stdin);while(~scanf(%d,n)){nxnyn;for(int i1;in;i)for(int j1;jn;j)scanf(%d,w[i][j]);int ansKM();printf(%d\n,ans);}return 0;
}
最短路径问题
dijstra
#includeiostream
#includecstdio
#includecstring
#includequeue
#includealgorithm
using namespace std;
const int MAXN10010,MAXM500010;
int inf2147483647;
struct XY{int w,to,pre;
}e[MAXM];struct XX{int dis,num;
}d[MAXN],tmp;struct cmp1{bool operator ()(XX a,XX b){return a.disb.dis;}
};int n,m,s,sz0;
int las[100010];
bool flag[MAXN];
priority_queueXX,vectorXX,cmp1 q;void add(int x,int y,int w){sz;e[sz].toy;e[sz].ww;e[sz].prelas[x];las[x]sz;
}void Dijkstra(){int min,u0;d[s].dis0;q.push(d[s]);while (!q.empty()){uq.top().num;q.pop();if (flag[u]) continue;flag[u]true;for (int jlas[u];j;je[j].pre){int mue[j].to;if (d[mu].disd[u].dise[j].w){d[mu].disd[u].dise[j].w;q.push(d[mu]);}}}
}int main(){int xx,yy,zz;cin nms;for (int i1;in;i){d[i].numi;d[i].disinf;}for (int i1;im;i){scanf(%d%d%d,xx,yy,zz);add(xx,yy,zz);}Dijkstra();for (int i1;in;i)printf(%d ,d[i].dis);cout endl;return 0;
}
#includebits/stdc.h
using namespace std;
#define maxn 10005
#define maxm 500005
#define INF 1234567890
inline int read()
{int x0,k1; char cgetchar();while(c0||c9){if(c-)k-1;cgetchar();}while(c0c9)x(x3)(x1)(c^48),cgetchar();return x*k;
}
struct Edge
{int u,v,w,next;
}e[maxm];
int head[maxn],cnt,n,m,s,vis[maxn],dis[maxn],pre[maxn];
struct node
{int w,now;inline bool operator (const node x)const//重载运算符把最小的元素放在堆顶大根堆{return wx.w;//这里注意符号要为}
};
priority_queuenodeq;
//优先队列其实这里一般使用一个pair但为了方便理解所以用的结构体
inline void add(int u,int v,int w)
{e[cnt].uu;//这句话对于此题不需要但在缩点之类的问题还是有用的e[cnt].vv;e[cnt].ww;e[cnt].nexthead[u];//存储该点的下一条边head[u]cnt;//更新目前该点的最后一条边就是这一条边
}
//链式前向星加边void print(int x)
{if(pre[x]0)return ;print(pre[x]);cout- x;
}
void dijkstra()
{for(int i1;in;i){dis[i]INF;}dis[s]0;//赋初值q.push((node){0,s});while(!q.empty())//堆为空即为所有点都更新{node xq.top();q.pop();int ux.now;//记录堆顶堆内最小的边并将其弹出if(vis[u]) continue; //没有遍历过才需要遍历vis[u]1;for(int ihead[u];i;ie[i].next)//搜索堆顶所有连边{int ve[i].v;if(dis[v]dis[u]e[i].w){dis[v]dis[u]e[i].w;pre[v]u;//松弛操作q.push((node){dis[v],v});//把新遍历到的点加入堆中}}}
}
int main()
{nread(),mread(),sread();for(int i1,x,y,z;im;i){xread(),yread(),zread();add(x,y,z);}dijkstra();for(int i1;in;i){printf(%d ,dis[i]);// print(i);// coutendl;}return 0;
}
SPFA
void SPFA(int x)
{d[x]0;for(int i1;in;i)d[i]OO;queueintQ;Q.push(x);inq[x]true;while(!Q.empty()){int kQ.front;Q.pop();inq[k]false;for(int ihead[k];i!0;iedge[i].next){int jedge[i].u ;if(d[j]d[k]edge[i].w ){d[j]d[k]edge[i].w;if(inq[j]!){Q.push(j);inq[k]true;} }}}
}
#includeiostream
#includecstdio
#includecstring
#includestring
#includequeue
const long long inf2147483647;
const int maxn10005;
const int maxm500005;
using namespace std;
int n,m,s,num_edge0;
int dis[maxn],vis[maxn],head[maxm];
struct Edge
{int next,to,dis;
}edge[maxm]; //结构体表示静态邻接表
void addedge(int from,int to,int dis) //邻接表建图
{ //以下是数据结构书上的标准代码不懂翻书看解释edge[num_edge].nexthead[from]; //链式存储下一条出边edge[num_edge].toto; //当前节点编号edge[num_edge].disdis; //本条边的距离head[from]num_edge; //记录下一次的出边情况
}
void spfa()
{queueint q; //spfa用队列这里用了STL的标准队列for(int i1; in; i) {dis[i]inf; //带权图初始化vis[i]0; //记录点i是否在队列中同dijkstra算法中的visited数组}q.push(s); dis[s]0; vis[s]1; //第一个顶点入队进行标记while(!q.empty()){int uq.front(); //取出队首q.pop(); vis[u]0; //出队标记for(int ihead[u]; i; iedge[i].next) //邻接表遍历不多解释了也可用vector代替{int vedge[i].to; if(dis[v]dis[u]edge[i].dis) //如果有最短路就更改{dis[v]dis[u]edge[i].dis;if(vis[v]0) //未入队则入队{vis[v]1; //标记入队q.push(v);}}}}
}
int main()
{cinmn;sn;for(int i1; im; i){int f,g,w;cinfgw; addedge(f,g,w); //建图有向图连一次边就可以了addedge(g,f,w);}spfa(); //开始跑spfacoutdis[1]endl; //否则打印最短距离return 0;
}
搜索
动态规划
计算几何
其他算法
快速输入输出
快读
inline int read(){int s0,w1;char chgetchar();while(ch0||ch9){if(ch-)w-1;chgetchar();}while(ch0ch9) ss*10ch-0,chgetchar();//s(s3)(s1)(ch^48);return s*w;
}快输
inline void write(int x)
{if(x0) {putchar(-);x -x;}if(x9) write(x / 10);putchar(x % 10 0);
}C大数
大数加法
string sum(string s1,string s2)
{if(s1.length()s2.length()){string temps1;s1s2;s2temp;}int i,j;for(is1.length()-1,js2.length()-1;i0;i--,j--){s1[i]char(s1[i](j0?s2[j]-0:0)); //注意细节if(s1[i]-010){s1[i]char((s1[i]-0)%100);if(i) s1[i-1];else s11s1;}}return s1;
}大数乘以整形数
string Multiply(string s,int x) //大数乘以整形数
{reverse(s.begin(),s.end());int cmp0;for(int i0;is.size();i){cmp(s[i]-0)*xcmp;s[i](cmp%100);cmp/10;}while(cmp){s(cmp%100);cmp/10;}reverse(s.begin(),s.end());return s;
}大数除以整形数
string Except(string s,int x) //大数除以整形数
{int cmp0,ok0;string ans;for(int i0;is.size();i){cmp(cmp*10s[i]-0);if(cmpx){ok1;ans(cmp/x0);cmp%x;}else{if(ok1)ans0; //注意这里啊。才找出错误}}return ans;
}大数乘法
string sum(string s1,string s2) //大数加法
{if(s1.length()s2.length()){string temps1;s1s2;s2temp;}int i,j;for(is1.length()-1,js2.length()-1;i0;i--,j--){s1[i]char(s1[i](j0?s2[j]-0:0)); //注意细节if(s1[i]-010){s1[i]char((s1[i]-0)%100);if(i) s1[i-1];else s11s1;}}return s1;
}string Mult(string s,int x) //大数乘以整形数
{reverse(s.begin(),s.end());int cmp0;for(int i0;is.size();i){cmp(s[i]-0)*xcmp;s[i](cmp%100);cmp/10;}while(cmp){s(cmp%100);cmp/10;}reverse(s.begin(),s.end());return s;
}
string Multfa(string x,string y) //大数乘法
{string ans;for(int iy.size()-1,j0;i0;i--,j){string tmpMult(x,y[i]-0);for(int k0;kj;k)tmp0;anssum(ans,tmp);}return ans;
}Java大数
博客讲解
A B
import java.math.BigDecimal;
import java.util.Scanner;public class Main {public static void main(String[] args) {// TODO Auto-generated method stubBigDecimal a, b;Scanner cin new Scanner(System.in);while (cin.hasNext()) {a cin.nextBigDecimal();b cin.nextBigDecimal();if (a.compareTo(b) 0) System.out.println(YES);else System.out.println(NO);}}}
大整数加法
import java.math.BigInteger;
import java.util.Scanner;public class Main {public static void main(String[] args) {// TODO Auto-generated method stubBigInteger a,b;Scanner cin new Scanner(System.in);a cin.nextBigInteger();b cin.nextBigInteger();System.out.println(a.add(b));}}
大数阶乘
import java.math.BigInteger;
import java.util.Scanner;public class Main {public static void main(String[] args) {BigInteger f[] new BigInteger[5500];f[0] f[1] BigInteger.ONE;for (int i 2; i 5000; i) {f[i] f[i - 1].multiply(BigInteger.valueOf(i));}Scanner cin new Scanner(System.in);while (cin.hasNext()) {int m cin.nextInt();System.out.println(f[m]);}}
}
大斐波那契数
import java.math.BigInteger;
import java.util.Scanner;public class Main {public static void main(String[] args) {// TODO Auto-generated method stubScanner cin new Scanner(System.in);BigInteger[] nums new BigInteger[1010];nums[1] new BigInteger(1);nums[2] new BigInteger(1);for(int i 3; i 1000; i)nums[i] nums[i - 1].add(nums[i - 2]);int T cin.nextInt();while(T 0){T--;int n cin.nextInt();System.out.println(nums[n]);}}}
A/B
import java.math.BigInteger;
import java.util.Scanner;public class Main {public static void main(String[] args) {// TODO Auto-generated method stubScanner cin new Scanner(System.in);int T cin.nextInt();while(T 0){T--;BigInteger a cin.nextBigInteger();BigInteger b cin.nextBigInteger();BigInteger d new BigInteger(9973);BigInteger z new BigInteger(0);for(BigInteger i new BigInteger(1); ; i i.add(new BigInteger(1))){BigInteger c b.multiply(i);if(c.mod(d).compareTo(a) 0){System.out.println(i.mod(d));break;}}}}}
莫队算法
博客讲解
常规莫队 #includebits/stdc.h
using namespace std;const int maxn50005;
long long int c[maxn];
long long int sum[maxn];struct node{long long int l,r,num;
}q[maxn];long long anss[maxn];long long int block;
long long int ans0;bool cmp(node a,node b)
{return (a.r/block)(b.r/block)?a.lb.l:a.rb.r;}
/*
//根据奇偶性排序
bool cmp(node a,node b)
{return pos[a.l]^pos[b.l]?pos[a.l]pos[b.l]:pos[a.l]1?a.rb.r:a.rb.r;} */inline void del(int x)
{sum[c[x]]--;ans-2*sum[c[x]]1;
}inline void add(int x)
{sum[c[x]];ans2*sum[c[x]]-1;
}int main()
{long long int n,m,k;cinnmk;blocksqrt(n);for(long long i1;in;i)cinc[i];for(long long i1;im;i){cinq[i].lq[i].r;q[i].numi;}sort(q1,q1m,cmp);int l1,r0;for(long long i1;im;i){long long qlq[i].l,qrq[i].r;while(lql){del(l);//l; }while(lql){// l--;add(--l);}while(rqr){// r;add(r);}while(rqr) {del(r--);// r--;}anss[q[i].num]ans;}for(long long i1;im;i)printf(%lld\n,anss[i]);return 0;
}
带修改莫队
int cmp(const node1 a,const node1 b)
{if (a.l/unit!b.l/unit) return a.l/unitb.l/unit;else if (a.r/unit!b.r/unit) return a.r/unitb.r/unit;else return a.xb.x;
}
主函数维护答案
void solve()
{int l1,r0,now0;for (int i1;im;i){while (rq[i].r) update(r1,1),r;while (rq[i].r) update(r,-1),r--;while (lq[i].l) update(l-1,1),l--;while (lq[i].l) update(l,-1),l;while (nowq[i].x) change(now1,1,l,r),now;while (nowq[i].x) change(now,-1,l,r),now--;ans[q[i].id]tot;}
}
修改通过change实现
void change(int bh,int z,int l,int r)
{if (ch[bh].xlch[bh].xr) update(ch[bh].x,-1); //删除从前的影响 swap(c[ch[bh].x],ch[bh].y); if (ch[bh].xlch[bh].xr) update(ch[bh].x,1); //添加影响
}