时间优化
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
gcd
int gcd(int a,int b) {
int r;
while(b>0) {
r=a%b;
a=b;
b=r;
}
return a;
}
dijkstra
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll maxn=2e6+10;
const ll big=1e9+10;
ll n,m,cnt=0;
struct edge{
ll val,to,nex;
}e[maxn];
ll head[maxn],a[maxn],dist[maxn],flag[maxn];
void init(){
for(ll i=1;i<=n;i++){
dist[i]=-1;
}
dist[1]=0;
return ;
}
void add(ll u,ll v,ll c){
cnt++;
if(v!=n) e[cnt].val=a[v]+c;
else e[cnt].val=c;
e[cnt].to=v;
e[cnt].nex=head[u];
head[u]=cnt;
return ;
}
ll findmin(){
ll loc=-1,minn=big;
for(ll i=1;i<=n;i++){
if(dist[i]!=-1)
if(flag[i]==0&&(loc==-1||minn>dist[i])){
loc=i;
minn=dist[i];
}
}
flag[loc]=1;
return loc;
}
void op(ll u){
for(ll i=head[u];i;i=e[i].nex){
ll t=e[i].to;
if(flag[t]==0){
if(dist[t]==-1){
dist[t]=dist[u]+e[i].val;
}else dist[t]=min(dist[t],dist[u]+e[i].val);
}
}
return ;
}
void dijkstra(){
for(ll i=1;i<=n;i++){
ll loc=findmin();
op(loc);
}
return ;
}
int main()
{
ll u,v,c;
cin>>n>>m;
for(ll i=1;i<=n;i++){
cin>>a[i];
}
for(ll i=1;i<=m;i++){
cin>>u>>v>>c;
add(u,v,c);
add(v,u,c);
}
if(n==1){
cout<<0<<endl;
return 0;
}
init();
dijkstra();
cout<<dist[n]<<endl;
return 0;
}
输入带空格的字符串
string s;
getline(cin,s);
优先队列
#include<bits/stdc++.h>
using namespace std;
const long long int maxn=5e5+10;
long long int n,k;
long long int flag[maxn];
long long int pre[maxn];
long long int nex[maxn],cnt[maxn],nn[maxn];
//pirority_queue template
struct node{
long long int num,val;
}a;
struct cmp{
bool operator ()(const node &x,const node &y) const
{
if(x.val!=y.val) return x.val>y.val;
return x.num>y.num;
}
};
priority_queue<node,vector<node>,cmp>pr;
int main()
{
long long int i,val,v,l,r,idx;
cin>>n>>k;
for(i=1;i<=n;i++){
pre[i]=i-1;
nex[i]=i+1;
cin>>val;
a.val=val;
a.num=i;
pr.push(a);
}
while(pr.size()!=n-k){
a=pr.top();
pr.pop();
idx=a.num;
v=a.val;
if(cnt[idx]==0){//who need to be removed
l=pre[idx];
r=nex[idx];
nex[l]=r;
pre[r]=l;
cnt[l]+=v;
cnt[r]+=v;
flag[idx]=1;
}else {//don't need to be removed
a.val+=cnt[idx];
cnt[idx]=0;
pr.push(a);
}
}
while(pr.empty()!=1){
a=pr.top();
pr.pop();
idx=a.num;
v=a.val;
nn[idx]=v+cnt[idx];
}
for(i=1;i<=n;i++){
if(nn[i]!=0){
cout<<nn[i]<<" ";
}
}
cout<<endl;
return 0;
}
substr
string s="123456";
cout<<s.substr(0,2);//起始位置,长度
欧拉筛
void ola(){
memset(primes,0,sizeof(primes));
for(ll i=2;i<=n;i++){
if(primes[i]==0){
cnt++;
a[cnt]=i;
}
for(ll j=1;j<=cnt&&a[j]*i<=n;j++){
primes[a[j]*i]=1;
if(i%a[j]==0)break;
}
}
}
拓扑排序
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll maxn=1e5+10;
ll n;
ll cntt=0;//ans
string ans[maxn];
ll cnt=0,idx=0;//点 边
ll rudu[maxn];
map<string ,ll>mp;
string a[maxn];
vector<string >v[maxn];
struct edge{
ll v,nex;
}e[maxn];
ll head[maxn];
struct cmp{
bool operator()(const string & x,const string &y)const {
return x>y;
}
};
priority_queue<string ,vector<string>,cmp>pr;
void init(){
string s;
for(ll i=1;i<=n;i++){
cin>>s;
ll len=s.length();
string t="";
for(ll j=0;j<len;j++){
if(s[j]!='.'){
t+=s[j];
}else {
v[i].push_back(t);
if(mp[t]==0){
cnt++;
a[cnt]=t;
mp[t]=cnt;
}
t="";
}
}
v[i].push_back(t);
if(mp[t]==0){
cnt++;
a[cnt]=t;
mp[t]=cnt;
}
t="";
}
return ;
}
void add(ll u,ll v){
idx++;
e[idx].v=v;
e[idx].nex=head[u];
head[u]=idx;
}
void toposort(){
for(ll i=1;i<=cnt;i++){
if(rudu[i]==0){
pr.push(a[i]);
}
}
while(pr.empty()!=1){
string s=pr.top();
pr.pop();
cntt++;
ans[cntt]=s;
ll u=mp[s];
for(ll i=head[u];i;i=e[i].nex){
ll v=e[i].v;
rudu[v]--;
if(rudu[v]==0){
pr.push(a[v]);
}
}
}
return ;
}
void solve(){
for(ll i=2;i<=n;i++){
if(v[i-1].size()==v[i].size()){
for(ll j=0;j<v[i].size();j++){
if(v[i-1][j]!=v[i][j]){
string u=v[i-1][j];
string vv=v[i][j];
rudu[mp[vv]]++;
add(mp[u],mp[vv]);
break;
}
}
}
}
toposort();
return ;
}
void show1(){
for(ll i=1;i<=n;i++){
for(ll j=0;j<v[i].size();j++){
cout<<v[i][j]<<' ';
}
cout<<endl;
}
return ;
}
void show(){
for(ll i=1;i<=cnt;i++){
cout<<ans[i];
if(i!=cnt) cout<<".";
else cout<<endl;
}
}
int main()
{
cin>>n;
init();
// show1();
solve();
// cout<<"YES"<<endl;
show();
return 0;
}
tarjan缩点
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll maxn=1e5+10;
ll n,m;
ll dfn[maxn],low[maxn];
ll w[maxn],ww[maxn];
ll head[maxn],hd[maxn];
ll rep[maxn];
ll cnt=0,cntt=0;
ll tim=0;
ll rudu[maxn];
ll ans=0;
ll dist[maxn];
ll vis[maxn];
struct edge{
ll v,nex,u;
}e[maxn],ed[maxn];
void add(ll u,ll v){
cnt++;
e[cnt].u=u;
e[cnt].v=v;
e[cnt].nex=head[u];
head[u]=cnt;
return ;
}
void init(){
memset(head,0,sizeof(head));
memset(hd,0,sizeof(hd));
memset(vis,0,sizeof(vis));
return ;
}
stack<ll>st;
void tarjan(ll u){
low[u]=dfn[u]=++tim;//时间戳 首次访问时间
vis[u]=1;
st.push(u);
for(ll i=head[u];i;i=e[i].nex){
ll v=e[i].v;
if(dfn[v]==0){
tarjan(v);
low[u]=min(low[u],low[v]);
}else if(vis[v]==1){
low[u]=min(low[u],dfn[v]);
}
}
// cout<<"YES"<<endl;
if(dfn[u]==low[u]){//出栈
while(st.empty()!=1){
ll t =st.top();
st.pop();
rep[t]=u;
if(u!=t)
w[u]+=w[t];
vis[t]=0;
if(u==t){
break;
}
}
}
return ;
}
queue<ll>q;
void toposort(){
for(ll i=1;i<=n;i++){
if(rep[i]==i&&rudu[i]==0){
q.push(i);
dist[i]=w[i];
}
}
while(q.empty()!=1){
ll u=q.front();
q.pop();
for(ll i=hd[u];i;i=ed[i].nex){
ll v=ed[i].v;
dist[v]=max(dist[v],dist[u]+w[v]);
rudu[v]--;
if(rudu[v]==0) q.push(v);
}
}
for(ll i=1;i<=n;i++){
if(rep[i]==i){
ans=max(ans,dist[i]);
}
}
return ;
}
void show(){
for(ll i=1;i<=n;i++){
cout<<w[i]<<' ';
}
cout<<endl;
for(ll i=1;i<=n;i++){
cout<<rep[i]<<' ';
}
cout<<endl;
}
int main()
{
init();
cin>>n>>m;
for(ll i=1;i<=n;i++){
cin>>w[i];
}
ll u,v;
for(ll i=1;i<=m;i++){
cin>>u>>v;
add(u,v);
}
for(ll i=1;i<=n;i++){
if(dfn[i]==0) tarjan(i);
}
for(ll i=1;i<=m;i++){
ll x=rep[e[i].u];
ll y=rep[e[i].v];
if(x!=y){
cntt++;
ed[cntt].v=y;
ed[cntt].u=x;
ed[cntt].nex=hd[x];
hd[x]=cntt;
rudu[y]++;
}
}
// show();
toposort();
cout<<ans<<endl;
return 0;
}
dijkstra(priority_queue优化)
#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll n,m;
ll cnt=0;
const ll maxn=2e5+10;
ll flag[maxn],a[maxn];
ll head[maxn];
ll dist[maxn];
const ll inf=1e7+10;
struct edge{
ll v,nex,val;
}e[maxn];
struct node{
ll num,w;
}nod;
struct cmp{
bool operator()(const node & x,const node & y)const {
if(x.w!=y.w) return x.w>y.w;
return x.num>y.num;
}
};
priority_queue<node ,vector<node>,cmp >pr;
void add(ll u,ll v,ll val){
cnt++;
e[cnt].v=v;
e[cnt].val=val;
e[cnt].nex=head[u];
head[u]=cnt;
return ;
}
void init(){
for(ll i=1;i<=n;i++){
dist[i]=inf;
}
dist[1]=0;
return ;
}
void dijkstra(){
nod.num=1;
nod.w=0;
pr.push(nod);
while(pr.empty()!=1){
nod=pr.top();
pr.pop();
ll u=nod.num;
ll w=nod.w;
if(flag[u]==1) continue;
flag[u]=1;
for(ll i=head[u];i;i=e[i].nex){
ll v=e[i].v;
if(flag[v]==0&&dist[u]+e[i].val<dist[v]){
dist[v]=dist[u]+e[i].val;
nod.num=v;
nod.w=dist[v];
pr.push(nod);
}
}
}
return ;
}
void show(){
for(ll i=1;i<=n;i++){
cout<<dist[i]<<' ';
}
cout<<endl;
return ;
}
int main()
{
memset(flag,0,sizeof(flag));
cin>>n>>m;
init();
for(ll i=1;i<=n;i++) cin>>a[i];
for(ll i=1;i<=m;i++){
ll u,v,val;
cin>>u>>v>>val;
add(u,v,val+a[v]);
add(v,u,val+a[u]);
}
dijkstra();
// show();
cout<<dist[n]-a[n]<<endl;
return 0;
}
spfa
实现方法:
建立一个队列,初始时队列里只有起始点,再建立一个表格记录起始点到所有点的最短路径(该表格的初始值要赋为极大值,该点到他本身的路径赋为0)。然后执行松弛操作,用队列里有的点作为起始点去刷新到所有点的最短路,如果刷新成功且被刷新点不在队列中则把该点加入到队列最后。重复执行直到队列为空。
判断有无负环:
如果某个点进入队列的次数超过N次则存在负环(SPFA无法处理带负环的图)
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll maxn=1e7+10;
const ll inf=maxn;
const ll mod=100003;
ll cnt=0;
struct edge{
ll v,nex;
}e[maxn];
ll head[maxn],vis[maxn],ans[maxn],dist[maxn];
ll n,m;
void add(ll u,ll v){
cnt++;
e[cnt].v=v;
e[cnt].nex=head[u];
head[u]=cnt;
return ;
}
void init(){
for(ll i=1;i<=n;i++){
dist[i]=inf;
}
memset(head,0,sizeof(head));
dist[1]=0;
ans[1]=1;
return;
}
void spfa(){
queue<ll>q;
q.push(1);
vis[1]=1;
while(q.empty()!=1){
ll u=q.front();
q.pop();
vis[u]=0;
for(ll i=head[u];i;i=e[i].nex){
ll v=e[i].v;
if(dist[v]>dist[u]+1){
dist[v]=dist[u]+1;
ans[v]=ans[u];
if(vis[v]==0){
q.push(v);
vis[v]=1;
}
}else if(dist[v]==dist[u]+1){
ans[v]=(ans[u]+ans[v])%mod;
}
}
}
return ;
}
int main()
{
cin>>n>>m;
init();
for(ll i=1;i<=m;i++){
ll u,v;
cin>>u>>v;
add(u,v);
add(v,u);
}
spfa();
for(ll i=1;i<=n;i++){
cout<<ans[i]<<endl;
}
return 0;
}
倍增lca
#include <bits/stdc++.h>
using namespace std;
const int N=500005,M=500005;//N存储节点总数,M存储边的总数
struct edge{
int to, next;
}e[M*2];//链式前向星存储边
int head[N],deep[N],fa[N][22],lg2[N];//head[]链式前向星 ,deep[]记录深度
//fa[i][j]表示i的2^j级祖先
//lg2数组记录log2(i)
int tot=0;//tot统计边数
bool vis[N];//节点访问标记
void add(int x,int y)//链式前项星加边
{
e[++tot].to=y;//存储节点
e[tot].next=head[x];//链表
head[x]=tot;//标记节点位置
}
void dfs(int x,int y=0)
{
if(vis[x]) return;//已经访问过,则已经得到deep和fa数组,返回
vis[x] = true;
deep[x]=deep[y]+1;//x是y的儿子节点,所以要+1
fa[x][0]=y;//fa[x][0]表示x的父亲节点,而y是x的父亲节点.
for(int i=1; i<=lg2[deep[x]]; i++) //因为x的2^i级祖先最多是根,则2^i<=dee[x],i<=lg2[deep[x]]
fa[x][i]=fa[fa[x][i-1]][i-1];//状态转移 2^i=2^(i-1)+2^(i-1)
for(int i=head[x]; i; i=e[i].next)
dfs(e[i].to,x);//访问儿子节点,并且标记自己是父亲节点
}
int LCA(int x,int y)
{
if(deep[x]<deep[y])//不妨让x节点是在y下方的节点
swap(x,y);//交换,维持性质
while(deep[x] != deep[y])//当我们还没有使得节点同样深度
x=fa[x][lg2[deep[x]-deep[y]]];//往上面跳跃,deep[x]-deep[y]是高度差.
if(x==y)//发现Lca(x,y)=y
return x;//返回吧,找到了...
for(int k=lg2[deep[x]]; k>=0; k--) //如何在x,y不相遇的情况下跳到尽可能高的位置?如果找到了这个位置,它的父亲就是LCA了
if(fa[x][k]!=fa[y][k])//如果发现x,y节点还没有上升到最近公共祖先节点
{
x=fa[x][k];//当然要跳跃
y=fa[y][k];//当然要跳跃
}
return fa[x][0];//必须返回x的父亲节点,也就是Lca(x,y)
}
int main()
{
int n,m,s,x,y;
scanf("%d%d%d",&n,&m,&s);//n个节点,m次询问,s为根节点
for(int i=1; i<n; i++) //n-1条边
{
scanf("%d%d",&x,&y);//读入边
add(x,y);//建立边
add(y,x);//建立无向图
}
for(int i=2; i<=n; i++)
lg2[i]=lg2[i/2]+1;//处理log数组的关系
dfs(s);//dfs预处理得到深度信息和祖先关系
for(int i=1; i<=m; i++)
{
scanf("%d%d",&x,&y);//读入需要查询的节点
printf("%d\n",LCA(x,y));//输出查询的结果
}
return 0;
}
全排列
#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll n;
ll a[100001];
void show(){
for(ll i=1;i<=n;i++) cout<<a[i]<<' ';
cout<<endl;
}
void prim(ll p){
if(p==n+1) {
show();
return ;
}
for(ll i=p;i<=n;i++){
ll t=a[i];
a[i]=a[p];
a[p]=t;
prim(p+1);
t=a[i];
a[i]=a[p];
a[p]=t;
}
}
int main()
{
cin>>n;
for(ll i=1;i<=n;i++) a[i]=i;
prim(1);
return 0;
}
最长上升子序列
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll inf=0x7f7f7f7f;
ll a[300003],low[300003];
ll find(ll l,ll r,ll x){
while(l<r){
ll mid=l+(r-l)/2;
if(low[mid]>=x){
r=mid;
}else l=mid+1;
}
return l;
}
int main()
{
ll n;
cin>>n;
for(ll i=1;i<=n;i++) {
cin>>a[i];
low[i]=inf;
}
low[1]=a[1];
ll ans=1;
for(ll i=2;i<=n;i++){
if(a[i]>low[ans]){
low[++ans]=a[i];
}else {
ll loc=find(1,ans,a[i]);
low[loc]=a[i];
}
}
cout<<ans<<endl;
return 0;
}
字符串增删改查
#include<bits/stdc++.h>
using namespace std;
#define ll long long
int main()
{
string s;
cin>>s;
ll n;
cin>>n;
for(ll i=1;i<=n;i++){
ll l,r;
string sl,sr,t;
cin>>l>>r>>sl>>sr;
t=s.substr(l-1,r-l+1);
s.erase(l-1,r-l+1);
string slr=sl+sr;
ll loc=s.find(slr);
if(loc==string::npos){//can not find
s+=t;
}else {//find it
s.insert(loc+sl.length(),t);
}
}
cout<<s<<endl;
return 0;
}