review
模板(水的一批)
线段树
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+5;
typedef long long LL;
int readint(){
int x=0,f=1;char s=getchar();
#define sc (s=getchar())
while(s<'0'||s>'9'){
if(s=='-')
f=-1;
sc;
}
while(s>='0'&&s<='9'){
x=(x<<3)+(x<<1)+(s^48);
sc;
}
#undef sc
return x*f;
}
/*segmentTree*/
LL a[maxn];
LL tree[maxn<<2],lazy[maxn<<2];
void build(int x,int l,int r){
if(l==r){
tree[x]=a[l];
lazy[x]=0;
return ;
}
int mid=(l+r)>>1;
build(x<<1,l,mid);
build(x<<1|1,mid+1,r);
tree[x]=tree[x<<1]+tree[x<<1|1];
}
void pushdown(int x,int l,int r){
int mid=(l+r)>>1;
lazy[x<<1]+=lazy[x];
tree[x<<1]+=lazy[x]*(mid-l+1);
lazy[x<<1|1]+=lazy[x];
tree[x<<1|1]+=lazy[x]*(r-mid);
lazy[x]=0;
}
void update(int x,int l,int r,int goal_l,int goal_r,int val){
if(l>=goal_l&&r<=goal_r){
lazy[x]+=val;
tree[x]+=val*(r-l+1);
return ;
}
pushdown(x,l,r);
int mid=(l+r)>>1;
if(goal_l<=mid)
update(x<<1,l,mid,goal_l,goal_r,val);
if(goal_r>mid)
update(x<<1|1,mid+1,r,goal_l,goal_r,val);
tree[x]=tree[x<<1]+tree[x<<1|1];
}
LL query(int x,int l,int r,int goal_l,int goal_r){
if(l>=goal_l&&r<=goal_r)
return tree[x];
pushdown(x,l,r);
int mid=(l+r)>>1;
LL ans=0;
if(goal_l<=mid)
ans+=query(x<<1,l,mid,goal_l,goal_r);
if(goal_r>mid)
ans+=query(x<<1|1,mid+1,r,goal_l,goal_r);
tree[x]=tree[x<<1]+tree[x<<1|1];
return ans;
}
int main (){
int n=readint(),m=readint();
for(int i=1;i<=n;i++)
a[i]=readint();
build(1,1,n);
for(int i=1;i<=m;i++){
int op=readint();
if(op==1){
int l=readint(),r=readint(),val=readint();
update(1,1,n,l,r,val);
// printf("%lld\n",query(1,1,n,l,r));
}
else{
int l=readint(),r=readint();
printf("%lld\n",query(1,1,n,l,r));
// printf("%d\n",tree[1]);
}
}
return 0;
}
树状数组(用CF251E的)
#include <bits/stdc++.h>
using namespace std;
#define lowbit(i) (i&(-i))
const int maxn = 2e3+5;
const int maxm = 2e5+5;
int readint(){
int x=0,f=1;char s=getchar();
#define sc (s=getchar())
while(s<'0'||s>'9'){
if(s=='-')
f=-1;
sc;
}
while(s>='0'&&s<='9'){
x=(x<<3)+(x<<1)+(s^48);
sc;
}
#undef sc
return x*f;
}
int FABS(int x){
if(x<0)
x=-x;
return x;
}
int a[maxn];
int l[maxn],r[maxn];
struct BIT{
int bit[maxm];
void add(int x){
for(int i=x;i<maxm;i+=lowbit(i))
bit[i]++;
}
int query(int x){
int ans=0;
for(int i=x;i;i-=lowbit(i))
ans+=bit[i];
return ans;
}
}s,p;
int main (){
int n=readint();
for(int i=1;i<=n;i++){
a[i]=FABS(readint())+1;
l[i]=s.query(a[i]-1);
s.add(a[i]);
}
for(int i=n;i>=1;i--){
r[i]=p.query(a[i]-1);
p.add(a[i]);
}
int ans=0;
for(int i=1;i<=n;i++){
ans+=min(l[i],r[i]);
}
printf("%d\n",ans);
return 0;
}
ST表
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+5;
int readint(){
int x=0,f=1;char s=getchar();
#define sc (s=getchar())
while(s<'0'||s>'9'){
if(s=='-')
f=-1;
sc;
}
while(s>='0'&&s<='9'){
x=(x<<3)+(x<<1)+(s^48);
sc;
}
#undef sc
return x*f;
}
int a[maxn];
int st[maxn][19];
void prepare(int n){
for(int i=1;i<=n;i++)
st[i][0]=a[i];
for(int j=1;j<=16;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]);
}
}
}
void query(int l,int r){
int k=log2(r-l+1);
printf("%d\n",max(st[l][k],st[r-(1<<k)+1][k]));
}
int main (){
int n=readint(),m=readint();
for(int i=1;i<=n;i++){
a[i]=readint();
}
prepare(n);
for(int i=1;i<=m;i++){
int l=readint(),r=readint();
query(l,r);
}
return 0;
}
tarjan
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 1e5+5;
int readint(){
int x=0,f=1;char s=getchar();
#define sc (s=getchar())
while(s<'0'||s>'9'){
if(s=='-')
f=-1;
sc;
}
while(s>='0'&&s<='9'){
x=(x<<3)+(x<<1)+(s^48);
sc;
}
#undef sc
return x*f;
}
int a[maxn];
struct edge{
int u,v,nxt;
edge(){};
edge(int U,int V,int N){
u=U;
v=V;
nxt=N;
}
}e[maxn];
int head[maxn],edge_cnt=-1;
void addedge(int u,int v){
e[++edge_cnt]=edge(u,v,head[u]);
head[u]=edge_cnt;
}
int dfn[maxn],low[maxn],dfn_cnt;
int st[maxn],top,scc[maxn],cnt;
int val[maxn];
bool vis[maxn];
void tarjan(int u){
dfn[u]=low[u]=++dfn_cnt;
vis[u]=1;
st[++top]=u;
for(int i=head[u];~i;i=e[i].nxt){
int v=e[i].v;
if(!dfn[v]){
tarjan(v);
low[u]=min(low[u],low[v]);
}
else if(vis[v])
low[u]=min(low[u],low[v]);
}
if(dfn[u]==low[u]){
scc[u]=++cnt;
vis[u]=0;
while(st[top]!=u){
scc[st[top]]=cnt;
vis[st[top]]=0;
top--;
}
top--;
}
}
vector<int> g[maxn];
int deg[maxn];
int dis[maxn];
void topo(){
queue<int> q;
for(int i=1;i<=cnt;i++){
if(!deg[i])
q.push(i);
dis[i]=val[i];
}
while(!q.empty()){
int u=q.front();
q.pop();
for(int i=0;i<g[u].size();i++){
int v=g[u][i];
dis[v]=max(dis[v],dis[u]+val[v]);
deg[v]--;
if(!deg[v])
q.push(v);
}
}
int maxx=0;
for(int i=1;i<=cnt;i++){
maxx=max(maxx,dis[i]);
// cout<<dis[i]<<endl;
}
printf("%d\n",maxx);
}
int main (){
// freopen("zz.in","r",stdin);
memset(head,-1,sizeof(head));
int n=readint(),m=readint();
// cout<<n<<" "<<m<<endl;
for(int i=1;i<=n;i++)
a[i]=readint();
for(int i=1;i<=m;i++){
int u=readint(),v=readint();
addedge(u,v);
}
for(int i=1;i<=n;i++){
if(!dfn[i]){
tarjan(i);
}
}
for(int i=1;i<=n;i++){
val[scc[i]]+=a[i];
// cout<<scc[i];
}
for(int i=0;i<=edge_cnt;i++)
if(scc[e[i].u]!=scc[e[i].v]){
g[scc[e[i].u]].push_back(scc[e[i].v]);
deg[scc[e[i].v]]++;
}
topo();
return 0;
}
并查集
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+5;
int readint(){
int x=0,f=1;char s=getchar();
#define sc (s=getchar())
while(s<'0'||s>'9'){
if(s=='-')
f=-1;
sc;
}
while(s>='0'&&s<='9'){
x=(x<<3)+(x<<1)+(s^48);
sc;
}
#undef sc
return x*f;
}
int fa[maxn];
int findset(int x){
if(fa[x]!=x)
fa[x]=findset(fa[x]);
return fa[x];
}
int main (){
int n=readint(),m=readint();
for(int i=1;i<=n;i++)
fa[i]=i;
for(int i=1;i<=m;i++){
int op=readint();
if(op==1){
int u=readint(),v=readint();
int fu=findset(u),fv=findset(v);
if(fu!=fv){
fa[fu]=fv;
}
}
else{
int u=readint(),v=readint();
int fu=findset(u),fv=findset(v);
if(fu==fv){
printf("Y\n");
}
else
printf("N\n");
}
}
return 0;
}
逆元
#include <bits/stdc++.h>
using namespace std;
const int maxn = 3e6+5;
int readint(){
int x=0,f=1;char s=getchar();
#define sc (s=getchar())
while(s<'0'||s>'9'){
if(s=='-')
f=-1;
sc;
}
while(s>='0'&&s<='9'){
x=(x<<3)+(x<<1)+(s^48);
sc;
}
#undef sc
return x*f;
}
int inv[maxn];
int main (){
int n=readint(),p=readint();
inv[0]=inv[1]=1;
for(int i=2;i<=n;i++){
inv[i]=(1ll*(p-p/i)*inv[p%i]+p)%p;
}
for(int i=1;i<=n;i++){
printf("%d\n",inv[i]);
}
return 0;
}
平衡树
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+5;
const int INF = 0x3f3f3f3f;
int readint(){
int x=0,f=1;char s=getchar();
#define sc (s=getchar())
while(s<'0'||s>'9'){
if(s=='-')
f=-1;
sc;
}
while(s>='0'&&s<='9'){
x=(x<<3)+(x<<1)+(s^48);
sc;
}
#undef sc
return x*f;
}
/*fhq Treap*/
int rt=0,len,key[maxn],rd[maxn];
int siz[maxn],cnt[maxn];
int son[maxn][2];
struct zz{
int p[2];
};
void pushup(int x){
siz[x]=siz[son[x][0]]+siz[son[x][1]]+cnt[x];
}
zz split(int x,int stkey){
zz ans;
ans.p[0]=ans.p[1]=0;
if(!x)
return ans;
int d=(key[x]<=stkey);
ans=split(son[x][d],stkey);
son[x][d]=ans.p[!d];
pushup(x);
ans.p[!d]=x;
return ans;
}
int merge(int x1,int y1){
if(!x1||!y1)
return y1^x1;
if(rd[x1]<=rd[y1]){
son[x1][1]=merge(son[x1][1],y1);
pushup(x1);
return x1;
}
else{
son[y1][0]=merge(x1,son[y1][0]);
pushup(y1);
return y1;
}
}
int insert(int x,int val){
zz t1=split(x,val);
zz t2=split(t1.p[0],val-1);//t2.0 t2.1 t1.1
if(t2.p[1]){
cnt[t2.p[1]]++;
pushup(t2.p[1]);
return merge(merge(t2.p[0],t2.p[1]),t1.p[1]);
}
++len;
cnt[len]=siz[len]=1;
key[len]=val;
rd[len]=rand();
son[len][0]=son[len][1]=0;
return merge(merge(t2.p[0],len),t1.p[1]);
}
int deleted(int x,int val){
zz t1=split(x,val);
zz t2=split(t1.p[0],val-1);
if(t2.p[1]&&cnt[t2.p[1]]>1){
cnt[t2.p[1]]--;
pushup(t2.p[1]);
return merge(merge(t2.p[0],t2.p[1]),t1.p[1]);
}
return merge(t2.p[0],t1.p[1]);
}
int getrank(int x,int val){
if(!x)
return 0;
if(val==key[x])
return siz[son[x][0]]+1;
if(val<key[x])
return getrank(son[x][0],val);
if(val>key[x])
return siz[son[x][0]]+cnt[x]+getrank(son[x][1],val);
}
int getnum(int x,int rk){
if(!x)
return 0;
if(rk>siz[son[x][0]]){
if(rk<=siz[son[x][0]]+cnt[x])
return key[x];
else
return getnum(son[x][1],rk-siz[son[x][0]]-cnt[x]);
}
else
return getnum(son[x][0],rk);
}
int getpre(int x,int val){
if(!x)
return -INF;
if(key[x]>=val)
return getpre(son[x][0],val);
else
return max(key[x],getpre(son[x][1],val));
}
int getsuf(int x,int val){
if(!x)
return INF;
if(key[x]<=val)
return getsuf(son[x][1],val);
else
return min(key[x],getsuf(son[x][0],val));
}
int main (){
// freopen("zz1.in","r",stdin);
srand(20050301);
rd[0]=200000000;
int n=readint();
while(n--){
int op=readint();
if(op==1){
int val=readint();
rt=insert(rt,val);
}
if(op==2){
int val=readint();
rt=deleted(rt,val);
}
if(op==3){
int val=readint();
printf("%d\n",getrank(rt,val));
}
if(op==4){
int rank=readint();
printf("%d\n",getnum(rt,rank));
}
if(op==5){
int val=readint();
int ans=getpre(rt,val);
if(ans==-INF)
puts("0");
else
printf("%d\n",ans);
}
if(op==6){
int val=readint();
int ans=getsuf(rt,val);
if(ans==INF)
puts("0");
else
printf("%d\n",ans);
}
}
return 0;
}
矩阵乘法和快速幂
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 1e2+5;
const int INF = 0x3f3f3f3f;
const int mo = 1e9+7;
int readint(){
int x=0,f=1;char s=getchar();
#define sc (s=getchar())
while(s<'0'||s>'9'){
if(s=='-')
f=-1;
sc;
}
while(s>='0'&&s<='9'){
x=(x<<3)+(x<<1)+(s^48);
sc;
}
#undef sc
return x*f;
}
struct matrix{
int n,m;
LL a[maxn][maxn];
matrix(){n=m=0,memset(a,0,sizeof(a));}
matrix operator *(const matrix &b)const{
matrix res;
res.n=n,res.m=b.m;
for(int i=1;i<=res.n;i++){
for(int k=1;k<=n;k++){
if(!a[i][k])
continue;
for(int j=1;j<=b.m;j++)
res.a[i][j]=(0ll+res.a[i][j]+1ll*a[i][k]*b.a[k][j]%mo)%mo;
}
}
return res;
}
}base;
matrix qkpow(matrix bas,LL b){
matrix ans;
ans.n=bas.n,ans.m=bas.m;
for(int i=1;i<=ans.n;i++)
ans.a[i][i]=1;
while(b){
if(b&1)
ans=ans*bas;
bas=bas*bas;
b>>=1;
}
return ans;
}
int main (){
int n=readint();
LL k;
scanf("%lld",&k);
base.n=base.m=n;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
base.a[i][j]=readint();
matrix ans=qkpow(base,k);
for(int i=1;i<=ans.n;i++){
for(int j=1;j<=ans.m;j++)
printf("%lld ",ans.a[i][j]);
puts("");
}
return 0;
}
LCA
#include <bits/stdc++.h>
using namespace std;
const int maxn = 5e5+5;
int readint(){
int x=0,f=1;char s=getchar();
#define sc (s=getchar())
while(s<'0'||s>'9'){
if(s=='-')
f=-1;
sc;
}
while(s>='0'&&s<='9'){
x=(x<<3)+(x<<1)+(s^48);
sc;
}
#undef sc
return x*f;
}
struct edge{
int v,nxt;
edge(){};
edge(int V,int N){
v=V;
nxt=N;
}
}e[maxn<<1];
int head[maxn],edge_cnt=-1;
void addedge(int u,int v){
e[++edge_cnt]=edge(v,head[u]);
head[u]=edge_cnt;
e[++edge_cnt]=edge(u,head[v]);
head[v]=edge_cnt;
}
int fa[maxn][20],dep[maxn];
void dfs(int u,int pre){
dep[u]=dep[pre]+1;
fa[u][0]=pre;
for(int j=1;j<=19;j++)
fa[u][j]=fa[fa[u][j-1]][j-1];
for(int i=head[u];~i;i=e[i].nxt){
int v=e[i].v;
if(v==pre)
continue;
dfs(v,u);
}
}
int getlca(int u,int v){
if(dep[u]>dep[v])
swap(u,v);
for(int j=19;j>=0;j--)
if(dep[fa[v][j]]>=dep[u])
v=fa[v][j];
if(u==v)
return u;
for(int j=19;j>=0;j--){
if(fa[u][j]!=fa[v][j]){
u=fa[u][j];
v=fa[v][j];
}
}
return fa[u][0];
}
int main (){
memset(head,-1,sizeof(head));
int n=readint(),m=readint(),rt=readint();
for(int i=1;i<n;i++){
int u=readint(),v=readint();
addedge(u,v);
}
dfs(rt,0);
while(m--){
int u=readint(),v=readint();
printf("%d\n",getlca(u,v));
}
return 0;
}
树链剖分
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+5;
typedef long long LL;
int readint(){
int x=0,f=1;char s=getchar();
#define sc (s=getchar())
while(s<'0'||s>'9'){
if(s=='-')
f=-1;
sc;
}
while(s>='0'&&s<='9'){
x=(x<<3)+(x<<1)+(s^48);
sc;
}
#undef sc
return x*f;
}
int m,rt,p,n;
int a[maxn];
/*brief in building tree*/
struct edge{
int v,nxt;
edge(){};
edge(int V,int N){
v=V;
nxt=N;
}
}e[maxn<<1];
int head[maxn],edge_cnt=-1;
void addedge(int u,int v){
e[++edge_cnt]=edge(v,head[u]);
head[u]=edge_cnt;
e[++edge_cnt]=edge(u,head[v]);
head[v]=edge_cnt;
}
int dep[maxn],son[maxn],siz[maxn],fa[maxn];//about dfs1 need
void dfs1(int u,int pre){
dep[u]=dep[pre]+1;
siz[u]=1;
fa[u]=pre;
for(int i=head[u];~i;i=e[i].nxt){
int v=e[i].v;
if(v==pre)
continue;
dfs1(v,u);
siz[u]+=siz[v];
if(siz[v]>siz[son[u]])
son[u]=v;
}
}
int dfn[maxn],rdfn[maxn],dfn_cnt;
int dfn_be[maxn],dfn_en[maxn],top[maxn];//about dfs2 find ancient
void dfs2(int u,int anc){
dfn[u]=++dfn_cnt;
rdfn[dfn_cnt]=u;
top[u]=anc;
dfn_be[u]=dfn_cnt;
if(son[u])
dfs2(son[u],anc);
for(int i=head[u];~i;i=e[i].nxt){
int v=e[i].v;
if(v==son[u]||v==fa[u])
continue;
dfs2(v,v);
}
dfn_en[u]=dfn_cnt;
}
/*segmentTree*/
int tree[maxn<<2],lazy[maxn<<2];
void pushdown(int x,int l,int r){
int mid=(l+r)>>1;
if(lazy[x]){
tree[x<<1]=(0ll+tree[x<<1]+1ll*lazy[x]*(mid-l+1)%p)%p;
lazy[x<<1]=(0ll+lazy[x<<1]+lazy[x])%p;
tree[x<<1|1]=(0ll+tree[x<<1|1]+1ll*lazy[x]*(r-mid)%p)%p;
lazy[x<<1|1]=(0ll+lazy[x<<1|1]+lazy[x])%p;
lazy[x]=0;
}
}
void build(int x,int l,int r){
if(l==r){
tree[x]=a[rdfn[l]]%p;
lazy[x]=0;
return ;
}
int mid=(l+r)>>1;
build(x<<1,l,mid);
build(x<<1|1,mid+1,r);
tree[x]=(tree[x<<1]+tree[x<<1|1])%p;
}
void update(int x,int l,int r,int goal_l,int goal_r,int val){
if(goal_l<=l&&goal_r>=r){
tree[x]=(0ll+tree[x]+1ll*(r-l+1)*val%p)%p;
lazy[x]=(0ll+lazy[x]+val)%p;
return;
}
pushdown(x,l,r);
int mid=(l+r)>>1;
if(goal_l<=mid)
update(x<<1,l,mid,goal_l,goal_r,val);
if(goal_r>mid)
update(x<<1|1,mid+1,r,goal_l,goal_r,val);
tree[x]=(0ll+tree[x<<1]+tree[x<<1|1])%p;
}
int query(int x,int l,int r,int goal_l,int goal_r){
if(goal_l<=l&&goal_r>=r)
return tree[x];
pushdown(x,l,r);
LL ans=0;
int mid=(l+r)>>1;
if(goal_l<=mid)
ans=(0ll+ans+query(x<<1,l,mid,goal_l,goal_r))%p;
if(goal_r>mid)
ans=(0ll+ans+query(x<<1|1,mid+1,r,goal_l,goal_r))%p;
tree[x]=(0ll+tree[x<<1]+tree[x<<1|1])%p;
return ans;
}
void modify(int x,int y,int val){
int tx=top[x],ty=top[y];
while(tx!=ty){
if(dep[tx]<dep[ty])
swap(x,y),swap(tx,ty);
update(1,1,n,dfn[tx],dfn[x],val);
x=fa[tx];
tx=top[x];
}
if(dep[x]>dep[y])
swap(x,y);
update(1,1,n,dfn[x],dfn[y],val);
}
int getans(int x,int y){
LL ans=0;
int tx=top[x],ty=top[y];
while(tx!=ty){
if(dep[tx]<dep[ty])
swap(x,y),swap(tx,ty);
ans=(0ll+ans+query(1,1,n,dfn[tx],dfn[x]))%p;
x=fa[tx];
tx=top[x];
}
if(dep[x]>dep[y])
swap(x,y);
ans=(0ll+ans+query(1,1,n,dfn[x],dfn[y]))%p;
return ans;
}
int main (){
memset(head,-1,sizeof(head));
n=readint(),m=readint(),rt=readint();p=readint();
for(int i=1;i<=n;i++)
a[i]=readint();
for(int i=1;i<n;i++){
int u=readint(),v=readint();
addedge(u,v);
}
dfs1(rt,0);
dfs2(rt,rt);
build(1,1,n);
for(int i=1;i<=m;i++){
int op=readint();
if(op==1){
int x=readint(),y=readint(),val=readint();
modify(x,y,val);
}
if(op==2){
int x=readint(),y=readint();
printf("%d\n",getans(x,y)%p);
}
if(op==3){
int x=readint(),val=readint();
update(1,1,n,dfn_be[x],dfn_en[x],val);
}
if(op==4){
int x=readint();
printf("%d\n",query(1,1,n,dfn_be[x],dfn_en[x])%p);
}
}
return 0;
}
最短路
给个 d i j s t r a dijstra dijstra吧 , , , s p f a spfa spfa死了
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+5;
typedef long long LL;
int readint(){
int x=0,f=1;char s=getchar();
#define sc (s=getchar())
while(s<'0'||s>'9'){
if(s=='-')
f=-1;
sc;
}
while(s>='0'&&s<='9'){
x=(x<<3)+(x<<1)+(s^48);
sc;
}
#undef sc
return x*f;
}
struct edge{
int v,w,nxt;
edge(){};
edge(int V,int W,int N){
v=V;
w=W;
nxt=N;
}
}e[maxn<<1];
int head[maxn],edge_cnt=-1;
void addedge(int u,int v,int w){
e[++edge_cnt]=edge(v,w,head[u]);
head[u]=edge_cnt;
// e[++edge_cnt]=edge(u,w,head[v]);
// head[v]=edge_cnt;
}
struct zz{
int u,d;
zz(){};
zz(int U,int D){
u=U;
d=D;
}
bool operator <(const zz &x)const{
return d>x.d;
}
};
int dis[maxn],vis[maxn];
void dijkstra(int n,int st){
for(int i=1;i<=n;i++)
dis[i]=0x3f3f3f3f;
priority_queue<zz> q;
dis[st]=0;
// vis[st]=1;
q.push(zz(st,0));
while(!q.empty()){
int u=q.top().u;
q.pop();
if(vis[u])
continue;
vis[u]=1;
for(int i=head[u];~i;i=e[i].nxt){
int v=e[i].v,w=e[i].w;
if(dis[v]>dis[u]+w){
dis[v]=dis[u]+w;
if(!vis[v])
q.push(zz(v,dis[v]));
}
}
}
}
signed main (){
memset(head,-1,sizeof(head));
// priority_queue<zz> q;
// q.push(zz(1,3));
// q.push(zz(2,1));
// printf("%d",q.top().u);
int n=readint(),m=readint(),s=readint();
for(int i=1;i<=m;i++){
int u=readint(),v=readint(),w=readint();
addedge(u,v,w);
}
dijkstra(n,s);
for(int i=1;i<=n;i++)
printf("%d ",dis[i]);
return 0;
}
最小生成树
prim
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 5e3+5;
const int maxm = 2e5+5;
const int INF = 0x3f3f3f3f;
int readint(){
int x=0,f=1;char s=getchar();
#define sc (s=getchar())
while(s<'0'||s>'9'){
if(s=='-')
f=-1;
sc;
}
while(s>='0'&&s<='9'){
x=(x<<3)+(x<<1)+(s^48);
sc;
}
#undef sc
return x*f;
}
struct edge{
int v,w,nxt;
edge(){};
edge(int V,int W,int N){
v=V;
w=W;
nxt=N;
}
}e[maxm<<1];
int head[maxn],edge_cnt=-1;
void addedge(int u,int v,int w){
e[++edge_cnt]=edge(v,w,head[u]);
head[u]=edge_cnt;
e[++edge_cnt]=edge(u,w,head[v]);
head[v]=edge_cnt;
}
int dis[maxn],vis[maxn];
void prim(int n){
for(int i=2;i<=n;i++)
dis[i]=INF;
for(int i=head[1];~i;i=e[i].nxt){
int v=e[i].v,w=e[i].w;
dis[v]=min(dis[v],e[i].w);
}
vis[1]=1;
int cnt=1;
LL ans=0;
while(cnt<n){
int minx=0x3f3f3f3f,now=0;
for(int i=1;i<=n;i++){
if(!vis[i]&&minx>dis[i]){
minx=dis[i];
now=i;
}
}
if(minx==0x3f3f3f3f){
puts("orz");
return;
}
vis[now]=1;
ans+=minx;
for(int i=head[now];~i;i=e[i].nxt){
int v=e[i].v;
if(vis[v])
continue;
if(dis[v]>e[i].w)
dis[v]=e[i].w;
}
++cnt;
}
printf("%lld",ans);
}
int main (){
memset(head,-1,sizeof(head));
int n=readint(),m=readint();
for(int i=1;i<=m;i++){
int u=readint(),v=readint(),w=readint();
addedge(u,v,w);
}
prim(n);
return 0;
}
Kruskal
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 5e3+5;
const int maxm = 2e5+5;
const int INF = 0x3f3f3f3f;
int readint(){
int x=0,f=1;char s=getchar();
#define sc (s=getchar())
while(s<'0'||s>'9'){
if(s=='-')
f=-1;
sc;
}
while(s>='0'&&s<='9'){
x=(x<<3)+(x<<1)+(s^48);
sc;
}
#undef sc
return x*f;
}
struct edge{
int u,v,w;
edge(){};
edge(int U,int V,int W){
u=U;
v=V;
w=W;
}
}e[maxm<<1];
int fa[maxn];
int findset(int x){
if(fa[x]!=x)
fa[x]=findset(fa[x]);
return fa[x];
}
bool cmp(const edge &x,const edge &y){
return x.w<y.w;
}
void kruskal(int n,int m){
for(int i=1;i<=n;i++)
fa[i]=i;
int cnt=0;
LL ans=0;
for(int i=1;i<=m;i++){
int u=e[i].u,v=e[i].v;
int fu=findset(u),fv=findset(v);
if(fu!=fv){
cnt++;
fa[fu]=fv;
ans+=e[i].w;
}
if(cnt==n-1)
break;
}
if(cnt!=n-1)
puts("orz");
else
printf("%lld",ans);
}
int main (){
int n=readint(),m=readint();
for(int i=1;i<=m;i++)
e[i].u=readint(),e[i].v=readint(),e[i].w=readint();
sort(e+1,e+m+1,cmp);
kruskal(n,m);
return 0;
}
Trie
[ T J O I 2010 ] 阅 读 理 解 [TJOI2010]阅读理解 [TJOI2010]阅读理解
#include <bits/stdc++.h>
using namespace std;
const int maxn = 5e5+5;
int readint(){
int x=0,f=1;char s=getchar();
#define sc (s=getchar())
while(s<'0'||s>'9'){
if(s=='-')
f=-1;
sc;
}
while(s>='0'&&s<='9'){
x=(x<<3)+(x<<1)+(s^48);
sc;
}
#undef sc
return x*f;
}
int trie[maxn][26];
int flag[maxn];
bitset<1005> vis[maxn];
char c[25];
int len,cnt;
void insert(int ind){
int now=0;
for(int i=1;i<=len;i++){
if(!trie[now][c[i]-'a'])
trie[now][c[i]-'a']=++cnt;
now=trie[now][c[i]-'a'];
}
flag[now]=1;
vis[now][ind]=1;
}
void query(int n){
int now=0;
bool sign=0;
for(int i=1;i<=len;i++){
if(!trie[now][c[i]-'a']){
puts(" ");
sign=1;
break;
}
now=trie[now][c[i]-'a'];
}
if(sign)
return;
if(flag[now]){
for(int i=1;i<=n;i++)
if(vis[now][i])
printf("%d ",i);
}
puts("");
}
int main (){
int n=readint();
for(int i=1;i<=n;i++){
int cnt=readint();
while(cnt--){
scanf("%s",c+1);
len=strlen(c+1);
insert(i);
}
}
int m=readint();
for(int i=1;i<=m;i++){
scanf("%s",c+1);
len=strlen(c+1);
query(n);
}
return 0;
}
后缀数组
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e6+5;
int readint(){
int x=0,f=1;char s=getchar();
#define sc (s=getchar())
while(s<'0'||s>'9'){
if(s=='-')
f=-1;
sc;
}
while(s>='0'&&s<='9'){
x=(x<<3)+(x<<1)+(s^48);
sc;
}
#undef sc
return x*f;
}
char s[maxn];
int rank[maxn],sa[maxn];//从i开始的后缀的排名,排名为i的开始位置
int x[maxn],y[maxn];//第一关键字,第二关键字,基数排序的时候用的
int cnt[maxn];//统计字符集中每个的个数
int main (){
scanf("%s",s+1);
int n=strlen(s+1);
int maxsize=150;//字符集大小
for(int i=1;i<=n;i++){//先按第一个关键字存进桶里
x[i]=s[i];
// cout<<x[i]<<endl;
cnt[x[i]]++;
}
for(int i=2;i<=maxsize;i++)//累计起来,看每个字符在所有当中哪个位置
cnt[i]+=cnt[i-1];
for(int i=n;i>=1;i--)//第一个的位置
sa[cnt[x[i]]--]=i;
for(int k=1;k<=n;k<<=1){//倍增
int num=0;
//按照第二关键字从小到大排序
for(int i=n-k+1;i<=n;i++)//后面n-k+1没有字符了
y[++num]=i;
for(int i=1;i<=n;i++)//如果某个他是大于k的,那他是可以做另外一个字符串的后k个
if(sa[i]>k)
y[++num]=sa[i]-k;
for(int i=1;i<=maxsize;i++)//清空字符集
cnt[i]=0;
for(int i=1;i<=n;i++)//直接第一关键字排序
++cnt[x[i]];
for(int i=2;i<=maxsize;i++)
cnt[i]+=cnt[i-1];
for(int i=n;i>=1;i--)
sa[cnt[x[y[i]]]--]=y[i],y[i]=0;//如果第二关键字大的,肯定在同样的第一个关键字中排后面
swap(x,y);
x[sa[1]]=1;num=1;//后面的直接手动的赋一个字符,第一个字符直接给他
for(int i=2;i<=n;i++)
x[sa[i]]=(y[sa[i]]==y[sa[i-1]]&&y[sa[i]+k]==y[sa[i-1]+k])?num:++num;
//第一个关键字和第二个关键字都相同就前缀相同了,否则就重新赋值
if(num==n)
break;
maxsize=num;
}
for(int i=1;i<=n;i++){
printf("%d ",sa[i]);
}
return 0;
}
可持久化线段树
普通线段树
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e6+5;
int readint(){
int x=0,f=1;char s=getchar();
#define sc (s=getchar())
while(s<'0'||s>'9'){
if(s=='-')
f=-1;
sc;
}
while(s>='0'&&s<='9'){
x=(x<<3)+(x<<1)+(s^48);
sc;
}
#undef sc
return x*f;
}
int root[maxn],tree[maxn<<5],cnt,num;
int son[maxn<<5][2];
int a[maxn];
void build(int x,int l,int r){
if(l==r){
tree[x]=a[l];
return;
}
int mid=(l+r)>>1;
son[x][0]=++cnt;son[x][1]=++cnt;
build(son[x][0],l,mid);
build(son[x][1],mid+1,r);
}
void update(int x,int pre,int l,int r,int goal,int val){
if(l==r){
tree[x]=val;
return ;
}
int mid=(l+r)>>1;
if(goal<=mid){
son[x][1]=son[pre][1];
son[x][0]=++cnt;
update(son[x][0],son[pre][0],l,mid,goal,val);
}
else{
son[x][0]=son[pre][0];
son[x][1]=++cnt;
update(son[x][1],son[pre][1],mid+1,r,goal,val);
}
}
int query(int x,int l,int r,int goal){
if(l==r){
return tree[x];
}
int mid=(l+r)>>1;
if(goal<=mid)
return query(son[x][0],l,mid,goal);
else
return query(son[x][1],mid+1,r,goal);
}
int main (){
cnt=1;
int n=readint(),m=readint();
for(int i=1;i<=n;i++)
a[i]=readint();
root[0]=1;
build(1,1,n);
while(m--){
int ind=readint(),op=readint();
if(op==1){
int pos=readint(),val=readint();
num++;
root[num]=++cnt;
update(root[num],root[ind],1,n,pos,val);
}
else{
int pos=readint();
printf("%d\n",query(root[ind],1,n,pos));
root[++num]=root[ind];
}
}
return 0;
}
权值线段树
#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e5+5;
int readint(){
int x=0,f=1;char s=getchar();
#define sc (s=getchar())
while(s<'0'||s>'9'){
if(s=='-')
f=-1;
sc;
}
while(s>='0'&&s<='9'){
x=(x<<3)+(x<<1)+(s^48);
sc;
}
#undef sc
return x*f;
}
int a[maxn],tree[maxn<<5],b[maxn];
int son[maxn<<5][2];
int root[maxn],cnt;
void build(int x,int l,int r){
if(l==r){
tree[x]=0;
return;
}
int mid=(l+r)>>1;
son[x][0]=++cnt;son[x][1]=++cnt;
build(son[x][0],l,mid);
build(son[x][1],mid+1,r);
}
void update(int x,int pre,int l,int r,int val){
if(l==r){
tree[x]=tree[pre]+1;
return;
}
int mid=(l+r)>>1;
if(val<=mid){
son[x][1]=son[pre][1];
son[x][0]=++cnt;
update(son[x][0],son[pre][0],l,mid,val);
}
else{
son[x][0]=son[pre][0];
son[x][1]=++cnt;
update(son[x][1],son[pre][1],mid+1,r,val);
}
tree[x]=tree[son[x][0]]+tree[son[x][1]];
}
int query(int pre,int x,int l,int r,int rk){
if(l==r)
return b[l];
int mid=(l+r)>>1;
int k=tree[son[x][0]]-tree[son[pre][0]];
if(rk<=k)
return query(son[pre][0],son[x][0],l,mid,rk);
else
return query(son[pre][1],son[x][1],mid+1,r,rk-k);
}
int main (){
int n=readint(),m=readint();
for(int i=1;i<=n;i++){
b[i]=a[i]=readint();
}
sort(b+1,b+n+1);
int num=unique(b+1,b+n+1)-b-1;
for(int i=1;i<=n;i++)
a[i]=lower_bound(b+1,b+num+1,a[i])-b;
root[0]=++cnt;
build(root[0],1,num);
for(int i=1;i<=n;i++){
root[i]=++cnt;
update(root[i],root[i-1],1,num,a[i]);
}
while(m--){
int l=readint(),r=readint(),k=readint();
printf("%d\n",query(root[l-1],root[r],1,num,k));
}
return 0;
}
李超线段树
#include <bits/stdc++.h>
using namespace std;
const int maxn = 5e4+5;
int readint(){
int x=0,f=1;char s=getchar();
#define sc (s=getchar())
while(s<'0'||s>'9'){
if(s=='-')
f=-1;
sc;
}
while(s>='0'&&s<='9'){
x=(x<<3)+(x<<1)+(s^48);
sc;
}
#undef sc
return x*f;
}
double k[maxn<<2],b[maxn<<2];//y=kx+b
bool flag[maxn<<2];
double calc(double k,double b,int day){
return k*day+b;
}
void insert(int x,int l,int r,double nowk,double nowb){
int mid=(l+r)>>1;
double ansl=calc(nowk,nowb,l),ansr=calc(nowk,nowb,r);
if(!flag[x]){
flag[x]=1;
k[x]=nowk,b[x]=nowb;
return;
}
if(ansl<=calc(k[x],b[x],l)&&ansr<=calc(k[x],b[x],r))
return;
if(ansl>=calc(k[x],b[x],l)&&ansr>=calc(k[x],b[x],r)){
k[x]=nowk,b[x]=nowb;
return;
}
double ans1=calc(nowk,nowb,mid),ans2=calc(k[x],b[x],mid);
if(ans1>ans2)
swap(k[x],nowk),swap(b[x],nowb);
if(calc(k[x],b[x],l)>calc(nowk,nowb,l))
insert(x<<1|1,mid+1,r,nowk,nowb);
else
insert(x<<1,l,mid,nowk,nowb);
}
double query(int x,int l,int r,int goal){
if(!flag[x])
return 0;
if(l==r)
return max(0.0,calc(k[x],b[x],goal));
int mid=(l+r)>>1;
double ans=max(0.0,calc(k[x],b[x],goal));
if(goal<=mid)
return max(ans,query(x<<1,l,mid,goal));
else
return max(ans,query(x<<1|1,mid+1,r,goal));
}
int main (){
// freopen("12.in","r",stdin);
// freopen("own.out","w",stdout);
int n=readint();
double maxx=0;
for(int i=1;i<=n;i++){
char c[10];
scanf("%s",c);
if(c[0]=='P'){
double k,b;
scanf("%lf %lf",&b,&k);
// cout<<"fuck"<<endl;
maxx=max(maxx,b);
insert(1,1,5e4,k,b);
}
else{
int goal=readint();
if(goal==1)
printf("%.0f\n",floor(maxx/100.0));
else
printf("%.0f\n",floor(query(1,1,5e4,goal-1)/100.0));
}
}
return 0;
}
白嫖一个我儿子的 m e r g e merge merge
inline int merge (int x, int y, int l, int r){
if (! x || ! y)
return (x | y);
int mid = l + r >> 1;
ch[x][0] = merge (ch[x][0], ch[y][0], l, mid);//先更新儿子
ch[x][1] = merge (ch[x][1], ch[y][1], mid + 1, r);
if (w (x, mid) < w (y, mid))//存中点值较大的一条线段
swap (k[x], k[y]), swap (b[x], b[y]);
if (l < r)
insert (x, l, r, k[y], b[y], y);
return x;
}
数论
应该不会怎么考吧,看看以前的,不打算写了
manacher(等待更新)
kmp(等待更新)
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e6+5;
int readint(){
int x=0,f=1;char s=getchar();
#define sc (s=getchar())
while(s<'0'||s>'9'){
if(s=='-')
f=-1;
sc;
}
while(s>='0'&&s<='9'){
x=(x<<3)+(x<<1)+(s^48);
sc;
}
#undef sc
return x*f;
}
char s[maxn],t[maxn];
int nxt[maxn];
void getnext(){
int n=strlen(t+1);
int j=0;
nxt[1]=0;
for(int i=2;i<=n;i++){
while(j&&t[i]!=t[j+1])
j=nxt[j];
if(t[i]==t[j+1])
j++;
nxt[i]=j;
}
}
void getind(){
int j=0;int n=strlen(t+1),len=strlen(s+1);
for(int i=1;i<=len;i++){
while(j&&s[i]!=t[j+1])
j=nxt[j];
if(s[i]==t[j+1])
j++;
if(j==n){
printf("%d\n",i-n+1);
j=nxt[j];
}
}
}
int main (){
scanf("%s",s+1);
scanf("%s",t+1);
getnext();
getind();
for(int i=1;i<=strlen(t+1);i++){
printf("%d ",nxt[i]);
}
return 0;
}
杂题
贪心
CodeForces - 549G
TP
考虑
a
[
i
]
+
i
a[i]+i
a[i]+i的总和不变
而后可以确定一个数在i位置上的值
因为保证他单调非递减
a
[
i
]
+
i
a[i]+i
a[i]+i排序后必须保证后一个严格大于前一个,不然相同就无解
此题解之
#include <bits/stdc++.h>
using namespace std;
int readint(){
int x=0,f=1;char s=getchar();
#define sc (s=getchar())
while(s<'0'||s>'9'){
if(s=='-')
f=-1;
sc;
}
while(s>='0'&&s<='9'){
x=(x<<3)+(x<<1)+(s^48);
sc;
}
#undef sc
return x*f;
}
int a[maxn];
int main (){
int n=readint();
for(int i=1;i<=n;i++){
a[i]=readint()+i;
}
sort(a+1,a+n+1);
for(int i=1;i<=n;i++){
if(a[i]==a[i+1]){
puts(":(");
return 0;
}
}
for(int i=1;i<=n;i++){
printf("%d ",a[i]-i);
}
return 0;
}
CF798D Mike and distribution
TP
显然取最多的数最香
所以要
n
/
2
+
1
n/2+1
n/2+1个
我们先优先保证
A
A
A
按
a
[
i
]
a[i]
a[i]从小到大排序
第一个必取
a
[
2
]
,
a
[
3
]
a[2],a[3]
a[2],a[3]选b更大的那个,则
B
B
B条件一定满足
此时如果最坏选的是
a
[
3
]
,
a
[
5
]
a[3],a[5]
a[3],a[5]等等
我们又把
[
1
,
2
]
[1,2]
[1,2]
[
3
,
4
]
[3,4]
[3,4] 这样分为一组可证明A也满足
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+5;
int readint(){
int x=0,f=1;char s=getchar();
#define sc (s=getchar())
while(s<'0'||s>'9'){
if(s=='-')
f=-1;
sc;
}
while(s>='0'&&s<='9'){
x=(x<<3)+(x<<1)+(s^48);
sc;
}
#undef sc
return x*f;
}
struct zz{
int a,b,ind;
}s[maxn];
bool cmp(const zz &x,const zz &y){
return x.a>y.a;
}
int main (){
int n=readint();
for(int i=1;i<=n;i++){
s[i].ind=i;
s[i].a=readint();
}
for(int i=1;i<=n;i++)
s[i].b=readint();
sort(s+1,s+n+1,cmp);
printf("%d\n",n/2+1);
printf("%d",s[1].ind);
for(int i=2;i<=n;i+=2){
if(s[i].b>=s[i+1].b)
printf(" %d",s[i].ind);
else
printf(" %d",s[i+1].ind);
}
return 0;
}
[CodeForces-351E]
TP
此题竟然可以无限取反符号,
那我们不如都取反后再处理
对于一个数来说它取成负号会让他前面比它小的数的全部形成逆序对
把后面比他小的数的逆序对全部消失
二者取最小即可
如果将这个数取反后,
会影响后面的数吗?
显然不会
#include <bits/stdc++.h>
using namespace std;
#define lowbit(i) (i&(-i))
const int maxn = 2e3+5;
const int maxm = 2e5+5;
int readint(){
int x=0,f=1;char s=getchar();
#define sc (s=getchar())
while(s<'0'||s>'9'){
if(s=='-')
f=-1;
sc;
}
while(s>='0'&&s<='9'){
x=(x<<3)+(x<<1)+(s^48);
sc;
}
#undef sc
return x*f;
}
int FABS(int x){
if(x<0)
x=-x;
return x;
}
int a[maxn];
int l[maxn],r[maxn];
struct BIT{
int bit[maxm];
void add(int x){
for(int i=x;i<maxm;i+=lowbit(i))
bit[i]++;
}
int query(int x){
int ans=0;
for(int i=x;i;i-=lowbit(i))
ans+=bit[i];
return ans;
}
}s,p;
int main (){
int n=readint();
for(int i=1;i<=n;i++){
a[i]=FABS(readint())+1;
l[i]=s.query(a[i]-1);
s.add(a[i]);
}
for(int i=n;i>=1;i--){
r[i]=p.query(a[i]-1);
p.add(a[i]);
}
int ans=0;
for(int i=1;i<=n;i++){
ans+=min(l[i],r[i]);
}
printf("%d\n",ans);
return 0;
}