整理的各種模板 (隨時棄坑emmmmm)
阿新 • • 發佈:2018-10-15
esp print scan algorithm include 優化 down lazy algo
線段樹:
#include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #define lson rt<<1 #define rson rt<<1|1 #define ll long long using namespace std; inline ll read() { char c=getchar();ll num=0,f=1; for(;!isdigit(c);c=getchar()) if(c==‘-‘) f=-1; for(;isdigit(c);c=getchar()) num=num*10+c-‘0‘; return num*f; } const ll N=1e5+5; ll n,m; ll a[N]; struct Tree { ll len; //記錄掌管的區間的長度數(元素個數 ll maxn,minn,sum; //最大最小值、區間和 ll lazy; //lazy標記 }tree[N<<2]; inline void pushup(ll rt) //用兒子更新當前節點 { tree[rt].maxn=max(tree[lson].maxn,tree[rson].maxn); tree[rt].minn=min(tree[lson].minn,tree[rson].minn); tree[rt].sum=tree[lson].sum+tree[rson].sum; return; } void build(ll rt,ll l,ll r) //rt為當前的樹根,l,r為rt對應的區間 { tree[rt].len=r-l+1; //當前節點掌管的區間長度(元素個數 if(l==r) //建到葉子節點了 { tree[rt].maxn=a[l]; //rt就是位置l對應的節點 tree[rt].minn=a[l]; tree[rt].sum=a[l]; return; } ll mid=(l+r)>>1; build(lson,l,mid); //建左兒子rt*2,對應區間[l,mid] build(rson,mid+1,r); //建右兒子rt*2+1,對應區間[mid+1,r] pushup(rt); //更新當前區間 } inline void pushdown(ll rt) //下傳lazy標記 { if(tree[rt].lazy) { //更新孩子的lazy標記 tree[lson].lazy+=tree[rt].lazy; tree[rson].lazy+=tree[rt].lazy; //更新孩子的最大值 tree[lson].maxn+=tree[rt].lazy; tree[rson].maxn+=tree[rt].lazy; //更新孩子的最小值 tree[lson].minn+=tree[rt].lazy; tree[rson].minn+=tree[rt].lazy; //更新孩子的區間和 tree[lson].sum+=tree[rt].lazy*tree[lson].len; tree[rson].sum+=tree[rt].lazy*tree[rson].len; //lazy重置 tree[rt].lazy=0; } return; } void modify(ll rt,ll l,ll r,ll pos,ll val) //單點修改 { if(l==r) //找到pos對應的葉子節點了 { tree[rt].maxn+=val; tree[rt].minn+=val; tree[rt].sum+=val; return; } pushdown(rt); //下放當前區間lazy標記 ll mid=(l+r)>>1; if(pos<=mid) //pos在左兒子裏 modify(lson,l,mid,pos,val); else //在右兒子裏 modify(rson,mid+1,r,pos,val); pushup(rt); //更新當前區間 } void Modify(ll rt,ll l,ll r,ll L,ll R,ll val) //區間修改 { if(l==L&&r==R) //找到一個合法區間 { tree[rt].sum+=tree[rt].len*val; tree[rt].maxn+=val; tree[rt].minn+=val; tree[rt].lazy+=val; return; } pushdown(rt); ll mid=(l+r)>>1; if(R<=mid) Modify(lson,l,mid,L,R,val); else if(L>mid) Modify(rson,mid+1,r,L,R,val); else Modify(lson,l,mid,L,mid,val),Modify(rson,mid+1,r,mid+1,R,val); pushup(rt); //不要忘了pushup } ll query_sum(ll rt,ll l,ll r,ll L,ll R) //查詢區間和 { if(l==L&&r==R) //找到了一個合法區間,返回區間和 return tree[rt].sum; pushdown(rt); ll mid=(l+r)>>1; if(R<=mid) //查詢區間全在左子樹 return query_sum(lson,l,mid,L,R); else if(L>mid) //查詢區間全在右子樹 return query_sum(rson,mid+1,r,L,R); else //一塊在左子樹,一塊在右子樹 return query_sum(lson,l,mid,L,mid)+query_sum(rson,mid+1,r,mid+1,R); } ll query_max(ll rt,ll l,ll r,ll L,ll R) { if(l==L&&r==R) return tree[rt].maxn; pushdown(rt); ll mid=(l+r)>>1; if(R<=mid) return query_max(lson,l,mid,L,R); else if(L>mid) return query_max(rson,mid+1,r,L,R); else return max(query_max(lson,l,mid,L,mid),query_max(rson,mid+1,r,L,R)); } ll query_min(ll rt,ll l,ll r,ll L,ll R) { if(l==L&&r==R) return tree[rt].minn; pushdown(rt); ll mid=(l+r)>>1; if(R<=mid) return query_min(lson,l,mid,L,R); else if(L>mid) return query_min(rson,mid+1,r,L,R); else return min(query_min(lson,l,mid,L,mid),query_min(rson,mid+1,r,L,R)); }; ll opt; ll x,l,r,val; int main() { n=read(),m=read(); for(ll i=1;i<=n;++i) a[i]=read(); build(1,1,n); while(m--) { opt=read(); if(opt==2) { l=read(),r=read(); cout<<query_sum(1,1,n,l,r)<<‘\n‘; } else if(opt==1) { l=read(),r=read(),val=read(); Modify(1,1,n,l,r,val); } } return 0; }
st表:
#include<iostream> #include<cstdio> #include<algorithm> using namespace std; int n,m,f[100005][33],lg[100005]; int main() { scanf("%d%d",&n,&m); lg[0]=-1; for(int i=1;i<=n;++i) { scanf("%d",&f[i][0]); lg[i]=lg[i>>1]+1; } for(int j=1;j<=19;++j) { for(int i=1;i+(1<<j)-1<=n;++i) { f[i][j]=max(f[i][j-1],f[i+(1<<(j-1))][j-1]); } } for(int i=1,l,r;i<=m;++i) { scanf("%d%d",&l,&r); int k=lg[r-l+1]; cout<<max(f[l][k],f[r-(1<<k)+1][k])<<"\n"; } return 0; }
dijkstra(O(n2)):
#include<iostream> #include<queue> #include<cstring> #include<cstdio> #define maxn 500000+1 #define maxn1 10000+1 using namespace std; inline int qread() { char c=getchar();int num=0,f=1; for(;!isdigit(c);c=getchar()) if(c==‘-‘) f=-1; for(;isdigit(c);c=getchar()) num=num*10+c-‘0‘; return num*f; } struct Edge { int v,w,nxt; }edge[maxn]; int head[maxn],num; void ct(int u,int v,int w) { edge[++num].v=v; edge[num].w=w; edge[num].nxt=head[u]; head[u]=num; } int n,m,s; int dis[maxn1],vis[maxn1]; void dijkstra() { dis[s]=0; for(int i=1;i<=n;++i) { int minn=0x7fffffff,u=-1; for(int j=1;j<=n;++j) { if(!vis[j]&&dis[j]<minn) minn=dis[j],u=j; } if(u==-1) break; vis[u]=1; for(int j=head[u];j;j=edge[j].nxt) { int v=edge[j].v; if(!vis[v]&&dis[v]>dis[u]+edge[j].w) dis[v]=dis[u]+edge[j].w; } } } int main() { n=qread(),m=qread(),s=qread(); for(int i=1;i<=n;++i) dis[i]=0x7fffffff; for(int i=1,u,v,w;i<=m;++i) { u=qread(),v=qread(),w=qread(); ct(u,v,w); } dijkstra(); for(int i=1;i<=n;++i) printf("%d ",dis[i]); return 0; }
堆優化dijkstra(O(nlogn)):
#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#define maxn 200000+1
#define maxn1 100000+1
using namespace std;
struct Edge
{
int v,nxt,w;
}edge[maxn];
int num,head[maxn],n,m,s,dis[maxn1];
struct node
{
int x,y;
bool operator < (const node &a) const
{
return y>a.y;
}
};
inline void ct(int u,int v,int w)
{
edge[++num].v=v;
edge[num].w=w;
edge[num].nxt=head[u];
head[u]=num;
}
inline int qread()
{
char c=getchar();int num=0,f=1;
for(;!isdigit(c);c=getchar()) if(c==‘-‘) f=-1;
for(;isdigit(c);c=getchar()) num=num*10+c-‘0‘;
return num*f;
}
inline void dijkstra()
{
memset(dis,0x3f,sizeof(dis));
dis[s]=0;
priority_queue<node>q;
q.push((node){s,0});
while(!q.empty())
{
int u=q.top().x,d=q.top().y;
q.pop();
if(d!=dis[u]) continue;
for(int i=head[u];i;i=edge[i].nxt)
{
int v=edge[i].v;
if(dis[v]>dis[u]+edge[i].w)
{
dis[v]=dis[u]+edge[i].w;
q.push((node){v,dis[v]});
}
}
}
}
int main()
{
n=qread(),m=qread(),s=qread();
for(int i=1,u,v,w;i<=m;++i)
{
u=qread(),v=qread(),w=qread();
ct(u,v,w);
}
dijkstra();
for(int i=1;i<=n;++i)
cout<<dis[i]<<" ";
return 0;
}
堆:
#include<iostream>
#include<cstdio>
#include<queue>
using namespace std;
int n;
int main()
{
priority_queue<int ,vector<int> ,greater<int > >q;
scanf("%d",&n);
while(n--)
{
int k;
scanf("%d",&k);
if(k==1)
{
scanf("%d",&k);
q.push(k);
}
else
if(k==2)
printf("%d\n",q.top());
else
q.pop();
}
return 0;
}
並查集:
#include<iostream>
#include<cstdio>
#define X 10000+10
using namespace std;
int fa[X];
int find(int x)
{
if(fa[x]!=x) return fa[x]=find(fa[x]);
return x;
}
void fac(int x,int y)
{
x=find(x),y=find(y);
fa[x]=y;
}
bool pd(int x,int y)
{
if(find(x)==find(y)) return 1;
return 0;
}
int main()
{
int n,m,a,b,z;
cin>>n>>m;
for(int i=1;i<=n;++i)
fa[i]=i;
while(m--)
{
cin>>z>>a>>b;
if(z==1)
{
if(find(a)!=find(b))
fac(a,b);
}
if(z==2)
{
if(pd(a,b)==1) cout<<"Y"<<endl;
else
cout<<"N"<<endl;
}
}
return 0;
}
乘法逆元:
#include<iostream>
#include<algorithm>
#include<cstdio>
#define ll long long
using namespace std;
const int maxn=3e6+1;
ll inv[maxn],n,p;
int main()
{
scanf("%lld%lld",&n,&p);
inv[1]=1;
for(int i=2;i<=n;++i)
{
inv[i]=(ll)(p-p/i)*inv[p%i]%p;
}
for(int i=1;i<=n;++i)
{
cout<<inv[i]<<‘\n‘;
}
return 0;
}
整理的各種模板 (隨時棄坑emmmmm)