模板

xiaoxiao2021-02-28  142

快速读入 fread namespace fastIO { #define BUF_SIZE 100000 bool IOerror = 0; inline char nc() { static char buf[BUF_SIZE], *p1 = buf + BUF_SIZE, *pend = buf + BUF_SIZE; if(p1 == pend) { p1 = buf; pend = buf + fread(buf, 1, BUF_SIZE, stdin); if(pend == p1) { IOerror = 1; return -1; } } return *p1++; } inline bool blank(char ch) { return ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t'; } inline void rd(int &x) { char ch; while(blank(ch = nc())); if(IOerror) return; for(x = ch - '0'; (ch = nc()) >= '0' && ch <= '9'; x = x * 10 + ch - '0'); } #undef BUF_SIZE }; using namespace fastIO; 普通快速读入 inline int IN(int &x) { char c;int f=1; x=0; for(c=getchar();c<'0'||c>'9';c=getchar())if(c=='-')f=-1; for(;c>='0'&&c<='9';c=getchar())x=x*10+c-'0'; return f*x; } 快速幂+快速乘 inline LL multi(LL a,LL b) { LL ans=0; while(b) { if(b&1)ans=(ans+a)%mod; a=(a+a)%mod; b>>=1; } return (ans+mod)%mod; } inline LL Pow(LL a,LL b) { LL ans=1; while(b) { if(b&1)ans=multi(ans,a)%mod; a=multi(a,a)%mod; b>>=1; } return (ans+mod)%mod; } KMP nxt[0]=0;nxt[1]=0; int j=0; for(int i=2;i<=m;++i) { while(j&&b[i]!=b[j+1])j=nxt[j]; if(b[i]==b[j+1])j++; nxt[i]=j; } j=0; int k=-1; for(int i=1;i<=n&&k==-1;++i) { while(j&&a[i]!=b[j+1])j=nxt[j]; if(a[i]==b[j+1])j++; if(j==m) { k=i; break; } } AC自动机 #include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #include<queue> using namespace std; typedef long long LL; const int maxn=1e6+5; int cnt,root,n; char s[maxn]; int fail[maxn],last[maxn]; struct node { int nxt[26],cnt; }T[maxn]; inline int newnode() { cnt++; memset(T[cnt].nxt,0,sizeof(T[cnt].nxt)); T[cnt].cnt=0; fail[cnt]=0; last[cnt]=0; return cnt; } inline void insert(char *s) { int now=root; int i=0; while(s[i]) { if(!T[now].nxt[s[i]-'a'])T[now].nxt[s[i]-'a']=newnode(); now=T[now].nxt[s[i]-'a']; i++; } T[now].cnt++; } queue<int>Q; inline void build() { Q.push(root); while(!Q.empty()) { int k=Q.front(); Q.pop(); for(int i=0;i<26;++i) { if(!T[k].nxt[i]){T[k].nxt[i]=T[fail[k]].nxt[i];continue;} if(k!=root) { fail[T[k].nxt[i]]=T[fail[k]].nxt[i]; last[T[k].nxt[i]]=T[T[k].nxt[i]].cnt?fail[T[k].nxt[i]]:last[fail[T[k].nxt[i]]]; } Q.push(T[k].nxt[i]); } } } inline int find(char *s) { int k=root; int cnt=0; int i=0; while(s[i]) { int x=s[i]-'a'; k=T[k].nxt[x]; int p=k; while(p!=root&&T[p].cnt>=0) { cnt+=T[p].cnt; T[p].cnt=-1; p=last[p]; } i++; } return cnt; } int main() { int t; scanf("%d",&t); while(t--) { cnt=-1; root=newnode(); scanf("%d",&n); for(int i=1;i<=n;++i) { scanf("%s",s); insert(s); } build(); scanf("%s",s); printf("%d\n",find(s)); } return 0; } AC自动机上DP+DFS序转RMQ线段树维护区间修改 #include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #include<queue> using namespace std; typedef long long LL; const int maxn=3e5+5; int cnt,root,n,kase,w[20000+5],pos[20000+5]; int INDEX,in[maxn],out[maxn]; char s[maxn]; int fail[maxn]; int S[maxn*4],tag[maxn*4],MAX,L,R; int st[maxn],tot; struct edge { int v,nxt; }v[maxn*2]; inline void addedge(int x,int y) { v[tot]=(edge){y,st[x]}; st[x]=tot++; } struct node { int nxt[26],cnt; }T[maxn]; inline int newnode() { cnt++; memset(T[cnt].nxt,0,sizeof(T[cnt].nxt)); T[cnt].cnt=0; fail[cnt]=0; return cnt; } inline void insert(char *s) { int now=root; int i=0; while(s[i]) { if(!T[now].nxt[s[i]-'a'])T[now].nxt[s[i]-'a']=newnode(); now=T[now].nxt[s[i]-'a']; i++; } T[now].cnt++; } queue<int>Q; inline void build() { Q.push(root); while(!Q.empty()) { int k=Q.front(); Q.pop(); if(k!=root)addedge(fail[k],k); for(int i=0;i<26;++i) { if(!T[k].nxt[i]){T[k].nxt[i]=T[fail[k]].nxt[i];continue;} if(k!=root) { fail[T[k].nxt[i]]=T[fail[k]].nxt[i]; } Q.push(T[k].nxt[i]); } } } inline void DFS(int u,int fa) { in[u]=++INDEX; for(int i=st[u];~i;i=v[i].nxt) if(v[i].v!=fa)DFS(v[i].v,u); out[u]=INDEX; } inline void update(int k) { S[k]=max(S[k<<1],S[k<<1|1]); } inline void down(int k) { if(!tag[k])return ; tag[k<<1]=max(tag[k<<1],tag[k]); tag[k<<1|1]=max(tag[k<<1|1],tag[k]); S[k<<1]=max(S[k<<1],tag[k]); S[k<<1|1]=max(S[k<<1|1],tag[k]); tag[k]=0; } inline int ask(int l,int r,int k) { if(L<=l&&r<=R)return S[k]; int mid=(l+r)>>1; down(k); int res=0; if(L<=mid)res=max(res,ask(l,mid,k<<1)); if(R>mid)res=max(res,ask(mid+1,r,k<<1|1)); return res; } inline void add(int l,int r,int k) { if(L<=l&&r<=R) { S[k]=max(S[k],MAX); tag[k]=max(tag[k],MAX); return ; } int mid=(l+r)>>1; down(k); if(L<=mid)add(l,mid,k<<1); if(R>mid)add(mid+1,r,k<<1|1); update(k); } int main() { int t; scanf("%d",&t); while(t--) { scanf("%d",&n); cnt=-1; root=newnode(); tot=0; memset(st,-1,sizeof(st)); pos[0]=0; for(int i=1;i<=n;++i) { scanf("%s%d",s+pos[i-1],w+i); pos[i]=pos[i-1]+strlen(s+pos[i-1]); insert(s+pos[i-1]); } build(); INDEX=0; DFS(root,-1); int ans=0; memset(S,0,sizeof(S)); memset(tag,0,sizeof(tag)); for(int i=1;i<=n;++i) { MAX=0; int p=root; for(int j=pos[i-1];j<pos[i];++j) { p=T[p].nxt[s[j]-'a']; L=in[p];R=in[p]; int res=ask(1,INDEX,1); MAX=max(res,MAX); } MAX=MAX+w[i]; ans=max(ans,MAX); L=in[p];R=out[p]; add(1,INDEX,1); } printf("Case #%d: %d\n",++kase,ans); } return 0; } 主席树静态区间第K大 #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int maxn=1e5+5; struct node { int l,r,siz; }T[40*maxn]; int root[maxn],n,m,cnt,l,r,ll,rr,v[maxn],pos,w[maxn],d,kth; inline int get_id(int x) { return lower_bound(w,w+d,x)-w+1; } inline int build(int l,int r) { int k=cnt++; if(l==r) { T[k].siz=0; return k; } int mid=(l+r)>>1; T[k].l=build(l,mid); T[k].r=build(mid+1,r); T[k].siz=0; //printf("l=%d r=%d ld=%d rd=%d k=%d\n",l,r,T[k].l,T[k].r,k); return k; } inline int add(int l,int r,int k) { int now=cnt++; T[now]=T[k]; if(l==pos&&r==pos) { T[now].siz+=1; return now; } int mid=(l+r)>>1; if(mid>=pos)T[now].l=add(l,mid,T[k].l); else T[now].r=add(mid+1,r,T[k].r); T[now].siz=T[T[now].l].siz+T[T[now].r].siz; return now; } inline int quiry(int l,int r,int ll,int rr,int kth) { if(l==r)return l; int mid=(l+r)>>1; int tmp=T[T[rr].l].siz-T[T[ll].l].siz; if(tmp>=kth)return quiry(l,mid,T[ll].l,T[rr].l,kth); else return quiry(mid+1,r,T[ll].r,T[rr].r,kth-tmp); } int main() { while(scanf("%d%d",&n,&m)!=EOF) { cnt=0; for(int i=0;i<n;++i) { scanf("%d",&v[i]); w[i]=v[i]; } sort(w,w+n); d=unique(w,w+n)-w; root[0]=build(1,d); for(int i=1;i<=n;++i) { pos=get_id(v[i-1]); root[i]=add(1,d,root[i-1]); } for(int i=1;i<=m;++i) { scanf("%d%d%d",&l,&r,&kth); printf("%d\n",w[quiry(1,d,root[l-1],root[r],kth)-1]); } } return 0; } 整体二分动态区间第K大 #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N = 5e4 + 7; const int M = 1e5 + 7; const int INF = 1 << 30; struct Quiry { int x,y,z,id,tp; }Q[ N + M ],q1[ N + M ],q2[ N + M ]; int n,m,cnt,a[N],ans[N],x,y,z,idx; struct Bit { int T[N]; int n; inline void init(int c){n=c;memset(T, 0, sizeof(T));} inline void add(int x,int y){for(;x<=n;x+=x&-x)T[x] += y;} inline int sum(int u) { int ans = 0; for(;u;u-=u&-u)ans += T[u]; return ans; } }BIT; inline void solve(int l,int r,int AL,int AR) { if(l>r)return; if(AL==AR) { for(int i=l;i<=r;++i) if(Q[i].tp==2) ans[Q[i].id] = AL; return; } int AM = (AL + AR) >> 1; int p1=0,p2=0; for(int i=l;i<=r;++i) { if(Q[i].tp==1) { if(Q[i].x<=AM) { BIT.add(Q[i].id,Q[i].y); q1[++p1] = Q[i]; } else q2[++p2] = Q[i]; } else { int del = BIT.sum(Q[i].y) - BIT.sum(Q[i].x-1); if(del >= Q[i].z)q1[++p1] = Q[i]; else { Q[i].z -= del; q2[++p2] = Q[i]; } } } for(int i=1;i<=p1;++i)if(q1[i].tp==1)BIT.add(q1[i].id,-q1[i].y); for(int i=1;i<=p1;++i)Q[i+l-1] = q1[i]; for(int i=1;i<=p2;++i)Q[i+p1+l-1] = q2[i]; solve(l,l+p1-1,AL,AM); solve(l+p1,r,AM+1,AR); } int main() { int T; scanf("%d\n",&T); while(T--) { scanf("%d%d\n",&n,&m); cnt = idx = 0; for(int i=1;i<=n;++i) { scanf("%d",a+i); Q[++cnt] = (Quiry){a[i],1,0,i,1}; } for(int i=1;i<=m;++i) { char opt[2]; scanf("%s%d%d",opt,&x,&y); if(*opt=='Q') { scanf("%d\n",&z); ++idx; Q[++cnt] = (Quiry){x,y,z,idx,2}; } else { Q[++cnt] = (Quiry){a[x],-1,0,x,1}; a[x]=y; Q[++cnt] = (Quiry){a[x],1,0,x,1}; } } BIT.init(n); solve(1,cnt,-INF,INF); for(int i=1;i<=idx;++i)printf("%d\n",ans[i]); } return 0; } 分块求区间小于x的和 #include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #include<queue> #include<map> #include<set> #include<vector> #include<cmath> using namespace std; const int maxn=2e5+5,INF=1<<30; int pos[maxn],siz,n,m,x,ll[maxn],rr[maxn]; int a[maxn],b[maxn]; int main() { int t; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); memset(ll,0,sizeof(ll)); siz=floor(sqrt(n)+0.5); for(int i=1;i<=n;++i) { scanf("%d",&a[i]); b[i]=a[i]; pos[i]=(i-1)/siz+1; if(!ll[pos[i]])ll[pos[i]]=i; rr[pos[i]]=i; } int maxsize=(n-1)/siz+1; int L,R; for(int i=1;i<=maxsize;++i) { sort(b+ll[i],b+1+rr[i]); } for(int i=1;i<=m;++i) { scanf("%d%d%d",&L,&R,&x); int idl=pos[L],idr=pos[R]; int res=0; if(idl!=idr) { for(int j=L;j<=rr[idl];++j) if(a[j]<x)res++; for(int j=ll[idr];j<=R;++j) if(a[j]<x)res++; for(int j=idl+1;j<idr;++j) { int y=lower_bound(b+ll[j],b+1+rr[j],x)-b; if(b[y]>=x||y==rr[j]+1)y--; if(y>=ll[j])res+=y-ll[j]+1; } } else { for(int j=L;j<=R;++j) if(a[j]<x)res++; } printf("%d\n",res); } } return 0; } 莫队分块-小Z的袜子 #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> using namespace std; const int maxn=50000+5; typedef long long LL; struct pp { int l,r,id; LL ans1,ans2; }a[maxn]; LL c[maxn],sum[maxn],ans; int n,m,pos[maxn]; inline bool cmp(const pp &A,const pp &B) { return pos[A.l]<pos[B.l]||(pos[A.l]==pos[B.l]&&A.r<B.r); } inline bool cmp2(const pp &A,const pp &B) { return A.id<B.id; } inline LL gcd(LL a,LL b) { if(!b)return a; return gcd(b,a%b); } inline void modify(int p,int del) { ans+=(LL)2*del*sum[c[p]]+1; sum[c[p]]+=del; } int main() { while(scanf("%d%d",&n,&m)!=EOF) { memset(sum,0,sizeof(sum)); for(int i=1;i<=n;++i)scanf("%lld",&c[i]); for(int i=1;i<=m;++i)scanf("%d%d",&a[i].l,&a[i].r),a[i].id=i; int siz=floor(sqrt(n)); for(int i=1;i<=n;++i)pos[i]=(i-1)/siz+1; sort(a+1,a+1+m,cmp); ans=0; int L=1,R=0; for(int i=1;i<=m;++i) { if(a[i].r>R) { for(R=R+1;R<=a[i].r;++R)modify(R,+1); --R; } if(a[i].r<R)for(;R>a[i].r;--R)modify(R,-1); if(a[i].l>L)for(;a[i].l>L;++L)modify(L,-1); if(a[i].l<L) { for(L=L-1;a[i].l<=L;--L)modify(L,+1); L++; } if(a[i].l==a[i].r) { a[i].ans1=0; a[i].ans2=1; continue; } a[i].ans1=ans-(a[i].r-a[i].l+1); a[i].ans2=(LL)(a[i].r-a[i].l)*(a[i].r-a[i].l+1); //printf("test=%lld/%lld\n",a[i].ans1,a[i].ans2); LL GCD=gcd(a[i].ans1,a[i].ans2); a[i].ans1/=GCD; a[i].ans2/=GCD; } sort(a+1,a+1+m,cmp2); for(int i=1;i<=m;++i)printf("%lld/%lld\n",a[i].ans1,a[i].ans2); } return 0; } 树链剖分-树状数组动态权值和 #include<cstdio> #include<cstring> #include<algorithm> #include<iostream> using namespace std; typedef long long LL; const int maxn=1e5+5; int n,m,start,end,cnt,k,index,opt; int fa[maxn],st[maxn],dep[maxn]; int top[maxn],son[maxn],size[maxn],id[maxn]; int T[maxn],a[maxn]; struct node { int ed,w,nxt; }v[maxn*2]; inline void add(int x,int y,int z) { v[cnt]=(node){y,z,st[x]}; st[x]=cnt++; } inline void dfs(int u,int f) { fa[u]=f; son[u]=0;size[u]=1;dep[u]=dep[f]+1; int ma=0; for(int x=st[u];~x;x=v[x].nxt) { int y=v[x].ed; if(y!=f) { dfs(y,u); size[u]+=size[y]; if(size[y]>ma)son[u]=y; } } } inline void DFS(int u,int tp) { top[u]=tp; id[u]=++index; if(son[u])DFS(son[u],tp); for(int x=st[u];~x;x=v[x].nxt) { int y=v[x].ed; if(y!=fa[u]&&y!=son[u])DFS(y,y); } } inline void update(int x,int val) { for(;x<=n;x+=x&-x)T[x]+=val; } inline int get(int x) { int res=0; for(;x;x-=x&-x)res+=T[x]; return res; } inline int quiry(int u,int v) { int x=top[u],y=top[v]; int ans=0; while(x!=y) { if(dep[x]<dep[y])swap(x,y),swap(u,v); ans+=get(id[u])-get(id[x]-1); u=fa[x]; x=top[u]; } if(u==v)return ans; if(dep[u]<dep[v])swap(u,v); ans+=get(id[u])-get(id[v]); return ans; } int main() { while(~scanf("%d%d%d",&n,&m,&start)) { memset(st,-1,sizeof(st)); cnt=0; int x,y,z; for(int i=1;i<n;++i) { scanf("%d%d%d",&x,&y,&z); add(x,y,z); add(y,x,z); } dfs(1,0); index=0; DFS(1,1); memset(T,0,sizeof(T)); for(int i=0;i<2*n-2;i+=2) { int x=v[i].ed,y=v[i^1].ed; if(dep[x]<dep[y])swap(x,y); a[id[x]]=v[i].w; update(id[x],v[i].w); } for(int i=1;i<=m;++i) { scanf("%d",&opt); if(opt) { scanf("%d%d",&x,&y); int u=v[2*x-2].ed,z=v[2*x-1].ed; if(dep[u]<dep[z])swap(u,z); update(id[u],-a[id[u]]); a[id[u]]=y; update(id[u],y); } else { scanf("%d",&end); printf("%d\n",quiry(start,end)); start=end; } } } return 0; } 树链剖分-线段树动态权值和 #include<cstdio> #include<cstring> #include<algorithm> #include<iostream> using namespace std; typedef long long LL; const int maxn=1e5+5; int n,m,start,end,cnt,k,index,opt,L,R; int fa[maxn],st[maxn],dep[maxn]; int top[maxn],son[maxn],size[maxn],id[maxn]; int T[maxn*4],a[maxn],leaf[maxn]; struct node { int ed,w,nxt; }v[maxn*2]; inline void add(int x,int y,int z) { v[cnt]=(node){y,z,st[x]}; st[x]=cnt++; } inline void dfs(int u,int f) { fa[u]=f; son[u]=0;size[u]=1;dep[u]=dep[f]+1; int ma=0; for(int x=st[u];~x;x=v[x].nxt) { int y=v[x].ed; if(y!=f) { dfs(y,u); size[u]+=size[y]; if(size[y]>ma)son[u]=y; } } } inline void DFS(int u,int tp) { top[u]=tp; id[u]=++index; if(son[u])DFS(son[u],tp); for(int x=st[u];~x;x=v[x].nxt) { int y=v[x].ed; if(y!=fa[u]&&y!=son[u])DFS(y,y); } } inline void update(int k) { T[k]=T[k<<1]+T[k<<1|1]; } inline void build(int l,int r,int k) { if(l==r) { T[k]=a[l]; leaf[l]=k; return; } int mid=(l+r)>>1; build(l,mid,k<<1); build(mid+1,r,k<<1|1); update(k); } inline int ask(int l,int r,int k) { if(L<=l&&r<=R)return T[k]; int mid=(l+r)>>1; int res=0; if(L<=mid)res+=ask(l,mid,k<<1); if(R>mid)res+=ask(mid+1,r,k<<1|1); return res; } inline void modify(int x) { int k=leaf[x]; T[k]=a[x]; k>>=1; for(;k;k>>=1)update(k); } inline int quiry(int u,int v) { int x=top[u],y=top[v]; int ans=0; while(x!=y) { if(dep[x]<dep[y])swap(x,y),swap(u,v); //ans+=get(id[u])-get(id[x]-1); L=id[x],R=id[u]; ans+=ask(1,n,1); u=fa[x]; x=top[u]; } if(u==v)return ans; if(dep[u]<dep[v])swap(u,v); L=id[v]+1,R=id[u]; ans+=ask(1,n,1); return ans; } int main() { while(~scanf("%d%d%d",&n,&m,&start)) { memset(st,-1,sizeof(st)); cnt=0; int x,y,z; for(int i=1;i<n;++i) { scanf("%d%d%d",&x,&y,&z); add(x,y,z); add(y,x,z); } dfs(1,0); index=0; DFS(1,1); memset(T,0,sizeof(T)); for(int i=0;i<2*n-2;i+=2) { int x=v[i].ed,y=v[i^1].ed; if(dep[x]<dep[y])swap(x,y); a[id[x]]=v[i].w; } build(1,n,1); for(int i=1;i<=m;++i) { scanf("%d",&opt); if(opt) { scanf("%d%d",&x,&y); int u=v[2*x-2].ed,z=v[2*x-1].ed; if(dep[u]<dep[z])swap(u,z); a[id[u]]=y; modify(id[u]); } else { scanf("%d",&end); printf("%d\n",quiry(start,end)); start=end; } } } return 0; }

树链剖分-不带修改的树上路径权值[A,B]的和询问-离线树状数组

#include<cstdio> #include<cstring> #include<algorithm> #include<iostream> using namespace std; typedef long long LL; const int maxn=1e5+5; int n,m,start,end,cnt,k,index,opt; int fa[maxn],st[maxn],dep[maxn]; int top[maxn],son[maxn],size[maxn],id[maxn]; LL T[maxn],ans[maxn]; int a,b,x,y,z; struct node { int ed,nxt; }v[maxn*2]; struct Lv { int d,id; }w[maxn]; struct Quiry { int u,v,val,id,ty; }Q[maxn*2]; inline bool cmp(const Lv&A,const Lv&B) { return A.d<B.d; } inline bool cmp2(const Quiry&A,const Quiry&B) { return A.val<B.val; } inline void add(int x,int y) { v[cnt]=(node){y,st[x]}; st[x]=cnt++; } inline void dfs(int u,int f) { fa[u]=f; son[u]=0;size[u]=1;dep[u]=dep[f]+1; int ma=0; for(int x=st[u];~x;x=v[x].nxt) { int y=v[x].ed; if(y!=f) { dfs(y,u); size[u]+=size[y]; if(size[y]>ma)son[u]=y; } } } inline void DFS(int u,int tp) { top[u]=tp; id[u]=++index; if(son[u])DFS(son[u],tp); for(int x=st[u];~x;x=v[x].nxt) { int y=v[x].ed; if(y!=fa[u]&&y!=son[u])DFS(y,y); } } inline void update(int x,LL val) { for(;x<=n;x+=x&-x)T[x]+=val; } inline LL get(int x) { LL res=0; for(;x;x-=x&-x)res+=T[x]; return res; } inline LL quiry(int u,int v) { int x=top[u],y=top[v]; LL ans=0; while(x!=y) { if(dep[x]<dep[y])swap(x,y),swap(u,v); ans+=get(id[u])-get(id[x]-1); u=fa[x]; x=top[u]; } if(u==v)return ans+get(id[u])-get(id[u]-1); if(dep[u]<dep[v])swap(u,v); ans+=get(id[u])-get(id[v]-1); return ans; } int main() { while(~scanf("%d%d",&n,&m)) { memset(st,-1,sizeof(st)); cnt=0; for(int i=1;i<=n;++i) { scanf("%d",&w[i].d); w[i].id=i; } sort(w+1,w+1+n,cmp); for(int i=1;i<n;++i) { scanf("%d%d",&x,&y); add(x,y); add(y,x); } dfs(1,0); index=0; DFS(1,1); cnt=0; for(int i=1;i<=m;++i) { scanf("%d%d%d%d",&x,&y,&a,&b); Q[++cnt]=(Quiry){x,y,a-1,i,-1}; Q[++cnt]=(Quiry){x,y,b,i,1}; } sort(Q+1,Q+1+cnt,cmp2); memset(T,0,sizeof(T)); memset(ans,0,sizeof(ans)); int L=1; for(int i=1;i<=cnt;++i) { while(L<=n&&w[L].d<=Q[i].val) { update(id[w[L].id],w[L].d); L++; } ans[Q[i].id]+=(LL)Q[i].ty*quiry(Q[i].u,Q[i].v); } for(int i=1;i<m;++i)printf("%lld ",ans[i]); printf("%lld\n",ans[m]); } return 0; } 倍增LCA-树上权值和 #include<cstdio> #include<cstring> #include<algorithm> #include<vector> using namespace std; const int N =100010; struct Edge { int x,w; Edge(int x,int w):x(x),w(w){} }; vector<Edge> g[N]; vector<int> vec[N]; int fa[N][20],dep[N],h[N]; int n,Q; void dfs(int x,int p) { h[x]=h[p]+1; fa[x][0]=p; for(int i=1;i<20;++i) fa[x][i]=fa[fa[x][i-1]][i-1]; int y; for(int i=0;i<g[x].size();++i) { y=g[x][i].x; if(y==p) continue; dep[y]=dep[x]+g[x][i].w; dfs(y,x); } } int lca(int x,int y) { if(h[x]<h[y]) swap(x,y); int d=h[x]-h[y]; for(int i=0;i<20;++i) if((d>>i)&1) x=fa[x][i]; if(x==y) return x; for(int i=19;i>=0;--i) if(fa[x][i]!=fa[y][i]) { x=fa[x][i];y=fa[y][i]; } return fa[x][0]; } int main() { int t; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&Q); for(int i=1;i<=n;++i) g[i].clear(); int x,y,w; for(int i=1;i<n;++i) { scanf("%d%d%d",&x,&y,&w); g[x].push_back(Edge(y,w)); g[y].push_back(Edge(x,w)); } dfs(1,0); int u,v,ans; while(Q--) { scanf("%d%d",&u,&v); ans=dep[u]+dep[v]-2*dep[lca(u,v)]; printf("%d\n",ans); } } return 0; } 高斯消元 #include<iostream> #include<cstdio> #include<vector> #include<algorithm> #include<cstring> using namespace std; const double eps=1e-8; const int MAXN=1e3; typedef double Matrix[MAXN][MAXN]; Matrix a;//m行n+1列,从0开始 //增广矩阵,即a[i][n]是方程右边的常数 //结束后a[i][n]是第i个未知数的值 int dcmp(double x)//浮点数比较 { if(fabs(x)<eps) return 0; return x<0?-1:1; } void Gauss(Matrix &a,int m,int n) { //变成行阶梯形矩阵 for(int i=0;i<m;++i) { //列选主元 int r=i; for(int j=i+1;j<m;++j) { if(fabs(a[j][i])>fabs(a[r][i])) r=j; } if(r!=i) for(int j=0;j<=n;++j) swap(a[r][j],a[i][j]); //与第i+1~m-1行进行消元 for(int k=i+1;k<m;++k) { double f=a[k][i]/a[i][i]; for(int j=i;j<=n;++j) a[k][j]-=f*a[i][j]; } } } //n元线性方程组 int solve(Matrix &a,int m,int n) { Gauss(a,m,n); int r1=0;//系数矩阵的秩 int r2=0;//增广矩阵的秩 for(int i=0;i<m;++i) { bool zero=true; for(int j=0;j<=n;j++) { if(dcmp(a[i][j])) { if(j<n) r1++; r2++; zero=false; break; } } if(zero||r1<r2) break; } if(r1<r2) return -1;//无解 else if(r1==r2&&r1<n) return 0;//有无穷多解 else { //回代 for(int i=n-1;i>=0;--i) { for(int j=i+1;j<n;++j) { a[i][n]-=a[j][n]*a[i][j]; } a[i][n]/=a[i][i]; } return 1;//有唯一解 } } int main() { int n,m; while(scanf("%d%d",&n,&m)!=EOF) { for(int i=0;i<m;++i) { for(int j=0;j<=n;++j) { scanf("%lf",&a[i][j]); } } int ans=solve(a,m,n); if(ans<0) printf("No solutions\n"); else if(ans==0) printf("Many solutions\n"); else { for(int i=0;i<n;++i) { printf("%d\n",(int)(a[i][n]+0.5)); } } } return 0; } RMQ const int maxn=1e5+5; int a[maxn],T[4*maxn],n,res[maxn],L,R,leaf[maxn]; //Segment Tree inline void update(int k) { T[k]=T[k<<1]+T[k<<1|1]; } inline void build(int l,int r,int k) { if(l==r) { T[k]=a[l]; leaf[l]=k; return; } int mid=(l+r)>>1; build(l,mid,k<<1); build(mid+1,r,k<<1|1); update(k); } inline int ask(int l,int r,int k) { if(L<=l&&r<=R)return T[k]; int mid=(l+r)>>1; int res=0; if(L<=mid)res+=ask(l,mid,k<<1); if(R>mid)res+=ask(mid+1,r,k<<1|1); return res; } inline void modify(int x) { int k=leaf[x]; T[k]=a[x]; k>>=1; for(;k;k>>=1)update(k); } //ST table void rmq_init() { for(int i=1; i<=n; i++) f[i][0] = a[i]; int k=floor(log((double)n)/log(2.0)); for(int j=1; j<=k; j++) for(int i=n; i>=1; i--) { if(i+(1<<(j-1))<=n) f[i][j]=max(f[i][j-1],f[i+(1<<(j-1))][j-1]); } } int rmq(int i,int j) { int k = floor(log((double)(j-i+1))/log(2.0)); return max(f[i][k],f[j-(1<<k)+1][k]); } 匈牙利算法-矩阵 #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int maxn=100+5; int G[maxn][maxn],a[maxn*maxn],b[maxn*maxn],obj[maxn]; bool used[maxn]; int n,m,k,kase; inline bool DFS(int u) { for(int i=1;i<=m;++i) if(G[u][i]&&used[i]==0) { used[i]=1; if(obj[i]==0||DFS(obj[i])) { obj[i]=u; return 1; } } return 0; } inline int Hungarian() { int res=0; memset(obj,0,sizeof(obj)); for(int i=1;i<=n;++i) { memset(used,0,sizeof(used)); if(DFS(i))res++; } return res; } int main() { while(~scanf("%d%d%d",&n,&m,&k)) { memset(G,0,sizeof(G)); for(int i=1;i<=k;++i) { scanf("%d%d",a+i,b+i); G[a[i]][b[i]]=1; } int MAX=Hungarian(),ans=0; for(int i=1;i<=k;++i) { G[a[i]][b[i]]=0; int res=Hungarian(); G[a[i]][b[i]]=1; if(res<MAX)ans++; } printf("Board %d have %d important blanks for %d chessmen.\n",++kase,ans,MAX); } return 0; } 匈牙利算法-邻接表 #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int maxn=100+5,maxm=maxn*maxn; int st[maxn],obj[maxn]; bool used[maxn]; int n,m,k,x,y,z,cnt; struct node { int ed,nxt; }v[maxm]; inline void add(int x,int y) { ++cnt; v[cnt]=(node){y,st[x]}; st[x]=cnt; } inline bool DFS(int u) { for(int x=st[u];x;x=v[x].nxt) { int y=v[x].ed; if(used[y]==0) { used[y]=1; if(obj[y]==-1||DFS(obj[y])) { obj[y]=u; return 1; } } } return 0; } inline int Hungarian() { int res=0; memset(obj,-1,sizeof(obj)); for(int i=1;i<n;++i) { memset(used,0,sizeof(used)); if(DFS(i))res++; } return res; } int main() { while(~scanf("%d%d%d",&n,&m,&k)&&n) { memset(st,0,sizeof(st)); cnt=0; for(int i=1;i<=k;++i) { scanf("%d%d%d",&z,&x,&y); if(x==0||y==0)continue; add(x,y); } int MAX=Hungarian(); printf("%d\n",MAX); } return 0; } 带权二分图最大匹配KM #include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #include<vector> #include<queue> using namespace std; typedef long long LL; const int maxn=200+5,maxm=maxn*maxn,INF=1<<28; typedef pair<int,int> pai; char s[maxn]; int n,m,cnt,pos,ed; int lx[maxn],ly[maxn],slack[maxn],w[maxn],obj[maxn]; bool visx[maxn],visy[maxn]; vector<pai>M,H; int st[maxn]; struct node { int v,nxt,w; }v[maxm]; inline void add(int x,int y,int c,int z) { v[cnt]=(node){y,st[x],z}; st[x]=cnt++; } inline bool DFS(int u) { visx[u]=1; for(int x=st[u];~x;x=v[x].nxt) { int y=v[x].v; if(visy[y])continue; if(lx[u]+ly[y]==v[x].w) { visy[y]=1; if(obj[y]==-1||DFS(obj[y])) { obj[y]=u; w[y]=v[x].w; return 1; } }else slack[y]=min(slack[y],lx[u]+ly[y]-v[x].w); } return 0; } inline void KM() { for(int i=1;i<=M.size();++i)lx[i]=-INF,ly[i]=0; for(int i=1;i<=M.size();++i) for(int x=st[i];~x;x=v[x].nxt) lx[i]=max(lx[i],v[x].w);//min for(int i=1;i<=M.size();++i) { for(int j=1;j<=H.size();++j)slack[j]=INF; while(1) { memset(visx,0,sizeof(visx)); memset(visy,0,sizeof(visy)); if(DFS(i))break; int d=INF; for(int j=1;j<=H.size();++j) if(!visy[j])d=min(d,slack[j]); for(int j=1;j<=H.size();++j) { if(visx[j])lx[j]-=d; if(visy[j])ly[j]+=d; else slack[j]-=d; } } } } int main() { while(~scanf("%d%d",&n,&m)) { if(!n&&!m)break; memset(st,-1,sizeof(st)); memset(obj,-1,sizeof(obj)); memset(w,0,sizeof(w)); cnt=0; H.clear();M.clear(); for(int i=0;i<n;++i) { scanf("%s",s); for(int j=0;j<m;++j) if(s[j]=='H')H.push_back(pai(i,j)); else if(s[j]=='m')M.push_back(pai(i,j)); } for(int i=0;i<M.size();++i) { pos=i+1; for(int j=0;j<H.size();++j) { int ed=j+1; int cost=abs(M[i].first-H[j].first)+abs(M[i].second-H[j].second); add(pos,ed,1,-cost); } } KM(); int ans=0; for(int i=1;i<=H.size();++i)ans-=w[i]; printf("%d\n",ans); } return 0; } 最大流 #include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #include<queue> using namespace std; typedef long long LL; const int maxn=500+5,maxm=maxn*maxn,INF=1<<30; int n,src,des,x,y,z,m; int st[maxn],stp[maxn],cnt; struct node { int v,w,nxt; }v[maxm]; inline void add(int x,int y,int z) { v[cnt]=(node){y,z,st[x]}; st[x]=cnt++; } queue<int>Q; inline bool bfs() { memset(stp,-1,sizeof(stp)); while(!Q.empty())Q.pop(); stp[src]=0; Q.push(src); while(!Q.empty()) { int u=Q.front(); Q.pop(); for(int x=st[u];~x;x=v[x].nxt) { int y=v[x].v; if(v[x].w>0&&stp[y]==-1) { stp[y]=stp[u]+1; Q.push(y); } } } return stp[des]!=-1; } inline int dfs(int u,int f) { if(u==des)return f; int res; for(int x=st[u];~x;x=v[x].nxt) { int y=v[x].v; if(v[x].w>0&&stp[y]==stp[u]+1) { res=dfs(y,min(f,v[x].w)); if(res>0) { v[x].w-=res; v[x^1].w+=res; return res; } } } stp[u]=-1; return 0; } inline int Dinic() { int ans=0,res; while(bfs()) { while(res=dfs(src,INF)) { ans+=res; } } return ans; } int main() { while(~scanf("%d%d",&n,&m)) { cnt=0; memset(st,-1,sizeof(st)); src=1;des=m; for(int i=1;i<=n;++i) { scanf("%d%d%d",&x,&y,&z); add(x,y,z); add(y,x,-z); } int res=Dinic(); printf("%d\n",res); } return 0; } 最小费用最大流MCMF #include<bits/stdc++.h> using namespace std; #define INF 0x3f3f3f3f typedef long long LL; const int M=2010; const int N=510; struct edge { int to; int next; int cap; int cost; } e[11000]; int head[N],tot; int d[N], pre[N], path[N]; bool vis[N]; void init() { memset(head,-1,sizeof(head)); tot = 0; } void addedge(int s, int t, int cap, int cost) { e[tot].to=t; e[tot].cap=cap; e[tot].cost=cost; e[tot].next=head[s]; head[s] = tot++; e[tot].to=s; e[tot].cap=0; e[tot].cost=-cost; e[tot].next=head[t]; head[t] = tot++; } int spfa(int s, int t) { memset(d,-INF,sizeof(d)); memset(pre,-1,sizeof(pre)); memset(path,-1,sizeof(path)); memset(vis,false,sizeof(vis)); int res = d[0]; d[s] = 0; vis[s] = true; queue<int>q; q.push(s); while (!q.empty()) { int u = q.front(); q.pop(); vis[u] = false; for (int i = head[u]; ~i; i = e[i].next) { int v = e[i].to; if (d[v] < d[u] + e[i].cost && e[i].cap > 0) { d[v] = d[u] + e[i].cost; pre[v] = u; path[v] = i; if (!vis[v]) { vis[v] = true; q.push(v); } } } } return d[t] != res; } int MinCostMaxFlow(int s, int t,int &cost) { int flow; flow=cost=0; while (spfa(s, t)) { int minn = INF; for (int i = t; i != s && ~i; i = pre[i]) minn = min(minn, e[path[i]].cap); for (int i = t; i != s && ~i; i = pre[i]) { e[path[i]].cap -= minn; e[path[i] ^ 1].cap += minn; } if (d[t] < 0) break; flow += minn; cost += minn * d[t]; } return flow; } int main(void) { int n,m; while (cin>>n>>m) { init(); int s=0,t=n+1,cost; for (int i=1; i<=n; i++) { int a,b,c,d; cin>>a>>b>>c>>d; addedge(s,i,b,-a); addedge(i,t,d,c); } while (m--) { int u,v,k; cin>>u>>v>>k; addedge(u,v,INF,-k); addedge(v,u,INF,-k); } MinCostMaxFlow(s,t,cost); cout<<cost<<endl; } return 0; } //http://blog.csdn.net/qq_28954601/article/details/77149389 Dj+Heap struct Heap { int dis,u; bool operator <(const Heap&B) const { return dis>B.dis; } }; priority_queue<Heap> Q; inline void Dj(int s) { memset(inq,0,sizeof(inq)); memset(dis,127,sizeof(dis)); while(!Q.empty())Q.pop(); dis[s]=0; Q.push((Heap){0,s}); while(!Q.empty()) { Heap New=Q.top(); Q.pop(); if(inq[New.u])continue; int k=New.u; inq[k]=1; for(int x=st[k];x;x=a[x].next) { int y=a[x].ed; if(!vis[y]&&dis[y]>dis[k]+a[x].w) { dis[y]=dis[k]+a[x].w; Q.push((Heap){dis[y],y}); } } } } Dj次短路 #include <cstdio> #include <cstring> #include <queue> #include <algorithm> using namespace std; typedef long long LL; const int MAXN=1e5+5; const LL INF=1ll<<60; struct edge { int to; LL cost; edge(LL tv = 0, LL tc = 0):to(tv), cost(tc){} }; typedef pair<LL ,LL> P; int N, M, A, B, D; vector<edge> graph[MAXN]; priority_queue<P, vector<P>, greater<P> > Q; LL dist[MAXN]; LL dist2[MAXN]; void solve(){ //fill(dist, dist+N, INF); //fill(dist2, dist2+N, INF); for(int i = 1; i <= N;++i)dist[i]=dist2[i]=INF; while(!Q.empty())Q.pop(); dist[1] = 0; Q.push(P(0, 1)); while(!Q.empty()) { P p = Q.top(); Q.pop(); LL v = p.second, d = p.first; if(dist2[v] < d) continue; for(LL i = 0; i < graph[v].size(); i++) { edge e = graph[v][i]; LL d2 = d + e.cost; if(dist[e.to] > d2) { swap(dist[e.to], d2); Q.push(P(dist[e.to], e.to)); } if(dist2[e.to] > d2 && dist[v] < d2) { dist2[e.to] = d2; Q.push(P(dist2[e.to], e.to)); } } } } int main() { int t; scanf("%d",&t); while(t--) { scanf("%d%d", &N, &M); int MIN=1<<30; for(LL i = 1; i <= N;++i)graph[i].clear(); for(LL i = 0; i < M; i++) { scanf("%d%d%d", &A, &B, &D); graph[A].push_back(edge(B, D)); graph[B].push_back(edge(A, D)); if(A==N||B==N)MIN=min(D,MIN); } solve(); LL ans=min(dist[N]+(LL)MIN*2,dist2[N]); printf("%lld\n",ans); } return 0; } SPFA inline void SPFA(int s) { memset(dis,127,sizeof(dis)); memset(inq,0,sizeof(inq)); int l=0,r=0; q[++r]=s; inq[s]=1; dis[s]=0; while(l<r) { int k=q[++l]; inq[k]=0; for(int x=st[k];x;x=a[x].next) { int y=a[x].ed; if(dis[y]>dis[k]+a[x].val) { dis[y]=dis[k]+a[x].val; if(!inq[y]) { inq[y]=1; q[++r]=y; } } } } } 哈夫曼编码 #include<cstdio> #include<algorithm> #include<queue> using namespace std; const int maxn=1e6+5; //typedef pair<int,int> pai; typedef long long LL; struct pai { LL cnt,len; bool operator <(const pai &B)const { return (cnt>B.cnt)||(cnt==B.cnt&&len>B.len); } }; LL n,k,sum,ans,w[maxn]; priority_queue<pai>Q; int main() { while(~scanf("%lld%lld",&n,&k)) { while(!Q.empty())Q.pop(); for(int i=1;i<=n;++i)scanf("%lld",w+i); while(k!=2&&n%(k-1)!=1)w[++n]=0; for(int i=1;i<=n;++i)Q.push((pai){w[i],0}); ans=0; while(Q.size()!=1) { LL sum=0,L=0; pai now={0,0}; for(int i=1;i<=k;++i) { now=Q.top(); Q.pop(); sum+=now.cnt; L=max(now.len,L); } now.cnt=sum; now.len=L+1; Q.push(now); ans+=sum; } pai now=Q.top(); printf("%lld\n%lld\n",ans,now.len); } return 0; } Lucas定理 const int MAXN = 1010; const int mod = 1e9 + 7; LL inv[MAXN + 10], fac[MAXN + 10]; void init() { inv[0] = fac[0] = inv[1] = fac[1] = 1; for(int i = 1; i < MAXN; i++) fac[i] = fac[i - 1] * i % mod; for(int i = 2; i < MAXN; i++) inv[i] = (mod - (mod / i)) * inv[mod % i] % mod;//lucas定理求逆元 for(int i = 1; i < MAXN; i++) inv[i] = inv[i - 1] * inv[i] % mod; } inline LL C(int n, int m)//求组合数 C n,m { if(n<m)return 0; return (fac[n] * inv[m] % mod) * inv[n - m] %mod; } 欧拉线性筛->莫比乌斯函数+欧拉函数 int n,m,T,kase,mobius[maxn],cnt[maxn],L,R; LL ans; bool vis[maxn]; int prime[maxn],phi[maxn]; inline void get_mobius() { int L=0; mobius[1]=1; phi[1]=1; for(int i=2;i<maxn;++i) { if(!vis[i])mobius[i]=-1,prime[++L]=i,phi[i]=i-1; for(int j=1;i*prime[j]<maxn&&j<=L;++j) { mobius[i*prime[j]]-=mobius[i]; phi[i*prime[j]]=phi[i]*phi[prime[j]]; vis[i*prime[j]]=1; if(i%prime[j]==0) { mobius[i*prime[j]]=0; phi[i*prime[j]]=phi[i]*prime[j]; break; } } } } 莫比乌斯反演+区间差分线段覆盖 #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; typedef long long LL; const int maxn=1e6,mod=1e9+7; int n,m; LL F[maxn+5],f[maxn+5]; bool vis[maxn+5]; int prime[maxn+5],mobius[maxn+5]; inline void get() { int L=0; mobius[1]=1; for(int i=2;i<=maxn;++i) { if(!vis[i])prime[++L]=i,mobius[i]=-1; for(int j=1;i*prime[j]<=maxn&&j<=L;++j) { vis[i*prime[j]]=1; mobius[i*prime[j]]-=mobius[i]; if(i%prime[j]==0) { mobius[i*prime[j]]=0; break; } } } } int main() { get(); for(int i=1;i<=maxn;++i) { F[i]++; for(int j=i+1;j<=maxn;j+=i) F[j]++; } for(int i=1;i<=maxn;++i)F[i]=(F[i-1]+F[i])%mod; for(int i=1;i<=maxn;++i) if(mobius[i]) { for(int j=i;j<=maxn;j+=i)f[j]=(f[j]+mobius[i]*F[j/i])%mod; } for(int i=1;i<=maxn;++i)f[i]=(f[i]+f[i-1])%mod; while(~scanf("%d",&n)) { printf("%lld\n",(f[n]+mod)%mod); } return 0; } 扩展欧几里得算法EXGCD /* 本程序仅用于求整数解,即当C满足模gcd(a,b)为0时可应用*/ #include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> using namespace std; int a,b,c,x,y,t,x0,y0; inline int exgcd(int a,int b) { if (b==0) { x=1; y=0; return a; } // ax+by=gcd(a,b)->b=0,ax=gcd(a,0)=a->x=1,y=0 int T=exgcd(b,a%b),t=x; x=y; y=t-(a/b)*x; return T; /* 因为gcd(a,b)=gcd(b,a%b) 根据定理:ax+by=gcd(a,b) ax+by=bx1+(a%b)y1 -> ax+by=bx1+(a-(a/b)*b)y1[c++中 /相当于div ] ax+by=ay1+b(x1-(a/b)*y1) 所以x=y1,y=x1-(a/b)*y1 */ } int main() { freopen("exgcd.in","r",stdin); freopen("exgcd.out","w",stdout); scanf("%d%d%d",&a,&b,&c); t=exgcd(a,b); x0=x*(c/t); y0=y*(c/t); //对于c不是gcd(a,b)的情况。 printf("%d %d",x0,y0); return 0; } /* 本程序求出的是一个基础解,由基础解可求出其他整数解: 对于ax+by=gcd(a,b): X=x+b/gcd(a,b)*t,Y=y-a/gcd(a,b)*t, 对于ax+by=c: X=x0+b/gcd(a,b)*t,Y=y0-a/gcd(a,b)*t, 其中t为任意整数 */ Prim&Kruskal #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int maxn=500+5,INF=1<<28; int v[maxn][maxn],n,m,ans,dis[maxn]; bool inque[maxn]; inline void prim() { memset(inque,0,sizeof(inque)); for(int i=1;i<=n;++i)dis[i]=v[1][i]; inque[1]=1; ans=0; for(int i=2;i<=n;++i) { int mini=INF,k=-1; for(int j=1;j<=n;++j) if(!inque[j]&&dis[j]<mini) { mini=dis[j]; k=j; } ans=max(ans,mini); inque[k]=1; for(int j=1;j<=n;++j) if(!inque[j]&&dis[j]>v[k][j])dis[j]=v[k][j]; } } //const int maxn=3000+5,maxm=100000+5; struct nod { int u,v,w; }a[maxn]; int fa[maxn]; inline bool cmp(const nod&A,const nod&B) { return A.w<B.w; } inline int get(int u) { if(fa[u]==u)return u; return fa[u]=get(fa[u]); } inline void kruskal() { for(int i=1;i<=m;++i)scanf("%d%d%d",&a[i].u,&a[i].v,&a[i].w); for(int i=1;i<=n;++i)fa[i]=i; int size=n; sort(a+1,a+1+m,cmp); for(int i=1;i<=m;++i) { int fx=get(a[i].u),fy=get(a[i].v); if(fx!=fy) { fa[fx]=fy; size--; } } } int main() { return 0; } 数位DP typedef long long ll; int a[20]; ll dp[20][state];//不同题目状态不同 ll dfs(int pos,/*state变量*/,bool lead/*前导零*/,bool limit/*数位上界变量*/)//不是每个题都要判断前导零 { //递归边界,既然是按位枚举,最低位是0,那么pos==-1说明这个数我枚举完了 if(pos==-1) return 1;/*这里一般返回1,表示你枚举的这个数是合法的,那么这里就需要你在枚举时必须每一位都要满足题目条件,也就是说当前枚举到pos位,一定要保证前面已经枚举的数位是合法的。不过具体题目不同或者写法不同的话不一定要返回1 */ //第二个就是记忆化(在此前可能不同题目还能有一些剪枝) if(!limit && !lead && dp[pos][state]!=-1) return dp[pos][state]; /*常规写法都是在没有限制的条件记忆化,这里与下面记录状态是对应,具体为什么是有条件的记忆化后面会讲*/ int up=limit?a[pos]:9;//根据limit判断枚举的上界up;这个的例子前面用213讲过了 ll ans=0; //开始计数 for(int i=0;i<=up;i++)//枚举,然后把不同情况的个数加到ans就可以了 { if() ...s else if()... ans+=dfs(pos-1,/*状态转移*/,lead && i==0,limit && i==a[pos]) //最后两个变量传参都是这样写的 /*这里还算比较灵活,不过做几个题就觉得这里也是套路了 大概就是说,我当前数位枚举的数是i,然后根据题目的约束条件分类讨论 去计算不同情况下的个数,还有要根据state变量来保证i的合法性,比如题目 要求数位上不能有62连续出现,那么就是state就是要保存前一位pre,然后分类, 前一位如果是6那么这意味就不能是2,这里一定要保存枚举的这个数是合法*/ } //计算完,记录状态 if(!limit && !lead) dp[pos][state]=ans; /*这里对应上面的记忆化,在一定条件下时记录,保证一致性,当然如果约束条件不需要考虑lead,这里就是lead就完全不用考虑了*/ return ans; } ll solve(ll x) { int pos=0; while(x)//把数位都分解出来 { a[pos++]=x;//个人老是喜欢编号为[0,pos),看不惯的就按自己习惯来,反正注意数位边界就行 x/=10; } return dfs(pos-1/*从最高位开始枚举*/,/*一系列状态 */,true,true);//刚开始最高位都是有限制并且有前导零的,显然比最高位还要高的一位视为0嘛 } int main() { ll le,ri; while(~scanf("%lld%lld",&le,&ri)) { //初始化dp数组为-1,这里还有更加优美的优化,后面讲 printf("%lld\n",solve(ri)-solve(le-1)); } } //http://blog.csdn.net/wust_zzwh/article/details/52100392 矩阵快速幂 #include<cstdio> #include<cstring> #include<algorithm> #include<iostream> using namespace std; typedef long long LL; const int N=4; LL n , MOD; struct Matrix { LL mat[N][N]; void init() { memset(mat,0,sizeof(mat)); mat[0][0]=mat[0][2]=mat[0][3]=1; mat[1][0]=mat[2][1]=mat[3][2]=1; } void clear() { memset(mat,0,sizeof(mat)); for(int i = 0 ; i < N ; i++)mat[i][i]=1; } Matrix operator*(const Matrix& m)const { Matrix tmp; for(int i = 0 ; i < N ; i++) { for(int j = 0 ; j < N ; j++) { tmp.mat[i][j] = 0; for(int k = 0 ; k < N ; k++) { tmp.mat[i][j] += mat[i][k]*m.mat[k][j]%MOD; tmp.mat[i][j] %= MOD; } } } return tmp; } }a; LL Pow(Matrix &a,LL b) { if(b <= 3)return (2*n)%MOD; if(b == 4)return 9%MOD; b -= 4; Matrix ans; ans.clear(); while(b){ if(b&1)ans=ans*a; b>>=1; a=a*a; } LL sum = 0; sum += ans.mat[0][0]*9%MOD; sum += ans.mat[0][1]*6%MOD; sum += ans.mat[0][2]*4%MOD; sum += ans.mat[0][3]*2%MOD; return sum%MOD; } int main() { while(~scanf("%lld%lld",&n,&MOD)) { a.init(); printf("%lld\n",Pow(a,n)); } return 0; } 不相交线段转换+连续代价小于x的最大覆盖数 #include <iostream> #include <cstring> #include <algorithm> using namespace std; const int maxn=1000010; int n,m; struct node { int a,b; }x[maxn]; int l[maxn],r[maxn]; inline bool cmp(node x1, node x2){return x1.a<x2.a||(x1.a==x2.a&&x1.b < x2.b);} int main() { while(~scanf("%d%d",&n,&m)) { for(int i=1; i<=n; i++)scanf("%d%d",&x[i].a,&x[i].b); sort(x+1, x+n+1, cmp); int cnt=1; l[1]=x[1].a;r[1]=x[1].b; for(int i=2; i<=n; i++) { if(x[i].a<=r[cnt])r[cnt]=max(r[cnt],x[i].b); else ++cnt,l[cnt]=x[i].a,r[cnt]=x[i].b; } int ans=r[1]-l[1]+1+m,L=1,res=0; for(int i=2;i<=cnt;++i) { res+=l[i]-r[i-1]-1; while(res>m) { res-=l[L+1]-r[L]-1; L++; } ans=max(ans,r[i]-l[L]+1+m-res); } printf("%d\n",ans); } return 0; } 归并排序求逆序对 LL ans; int a[maxn],n,b[maxn]; inline void merge(int l,int r) { if(l>=r)return; int mid=(l+r)>>1; merge(l,mid); merge(mid+1,r); int L=l,R=mid+1; int cnt=l; while(L<=mid||R<=r) { if(L>mid||(a[R]<a[L]&&R<=r)) { b[cnt++]=a[R++]; ans+=mid-L+1; } else b[cnt++]=a[L++]; } for(int i=l;i<=r;++i)a[i]=b[i]; } Splay-数组实现 #include<cstdio> #define N 2000100 using namespace std; struct node { int l,r,d,size,fa; void reset() { l=r=d=size=fa=0; } }T[N]; int cnt,i,j,m,n,k,root=1,now; inline void updata(int u)//update { T[u].size=T[T[u].l].size+T[T[u].r].size+1; } inline void zag(int s)//left_rotate { int x=T[s].fa,y=T[x].fa,z=T[s].l; if(T[y].l==x)T[y].l=s;else T[y].r=s; T[s].fa=y; T[x].r=z;T[z].fa=x; T[s].l=x;T[x].fa=s; updata(x); updata(s); } inline void zig(int s)//right_rotate { int x=T[s].fa,y=T[x].fa,z=T[s].r; if(T[y].l==x)T[y].l=s;else T[y].r=s; T[s].fa=y; T[x].l=z;T[z].fa=x; T[s].r=x;T[x].fa=s; updata(x); updata(s); } inline void splay(int s) { while(T[s].fa) { int x=T[s].fa,y=T[x].fa; if(y) { if(T[y].l==x) { if(T[x].l==s)zig(x),zig(s); else zag(s),zig(s); } else { if(T[x].l==s)zig(s),zag(s); else zag(x),zag(s); } } else if(T[x].l==s)zig(s);else zag(s); } root=s; } inline int findkth(int x)//寻找第k大返回指针 { int s=root; while(1) { if(x==T[T[s].l].size+1)return s; if(x<=T[T[s].l].size)s=T[s].l; else x=x-T[T[s].l].size-1,s=T[s].r; } } inline int getkth(int x)//寻找x是第k大返回k { int s=root; int sum=0; while(1&&s) { if(x==T[s].d)return sum+T[T[s].l].size+1; else if(x<T[s].d)s=T[s].l; else sum+=T[T[s].l].size+1,s=T[s].r; } return sum; } inline void insert(int x)//插入x { int s=root; if(!cnt){T[++cnt].reset();T[cnt].d=x;T[cnt].size=1;return;} while(1) { if(!T[s].d){T[s].d=x;T[s].size=1;return;} if(x<T[s].d) { if(!T[s].l){T[s].l=++cnt;T[cnt].fa=s;} T[s].size++; s=T[s].l; } else { if(!T[s].r){T[s].r=++cnt;T[cnt].fa=s;} T[s].size++; s=T[s].r; } } } inline void del(int x) { int y=findkth(x); splay(y); if(T[y].l==0&&T[y].r==0) { cnt=0;return; } if(T[y].l==0) { T[T[y].r].fa=0; root=T[y].r; return; } if(T[y].r==0) { T[T[y].l].fa=0; root=T[y].l; return; } int d=getkth(x); int z=findkth(d-1); T[z].r=T[y].r; T[T[y].r].fa=z; root=T[y].l; T[root].fa=0; splay(z); } int main() { scanf("%d",&n); cnt=0; for(i=1;i<=n;++i) { scanf("%d",&now); insert(now); //if(i&1)printf("%d\n",find((i>>1)+1,root)); //if(!(i%7))splay(root); } return 0; } Splay序列修改-指针 #include <cstdio> #include <cstring> using namespace std; struct node { char val; int size; node *lch, *rch, *pa; node(int s = 0, node *p = 0, char v = 0, node *l = 0, node *r = 0) : size(s), pa(p), val(v), lch(l), rch(r) { } }*top; struct pair { node *first, *second; pair(node *fir = 0, node *sec = 0) { first = fir, second = sec; } }; char s[100005]; int size(node *p) { if (!p) return 0; return p->size; } node *Build(char *s, int len, node *p = 0) { if (len == 0) return 0; if (len == 1) return new node(1, p, *s); node *res = new node; int mid = len >> 1; res->pa = p; res->val = s[mid]; res->lch = Build(s, mid, res); res->rch = Build(s + mid + 1, len - mid - 1, res); res->size = size(res->lch) + size(res->rch) + 1; return res; } void update(node *x) { if (x) x->size = size(x->lch) + size(x->rch) + 1; } node *rotate(node *x) { node *y = x ->pa; x->pa = y->pa, y->pa = x; if (x->pa) (x->pa->lch == y) ? x->pa->lch = x : x->pa->rch = x; if (y->lch == x) { y->lch = x->rch, x->rch = y; if (y->lch) y->lch->pa = y; }else { y->rch = x->lch, x->lch = y; if (y->rch) y->rch->pa = y; } update(y), update(x); return x; } node *splay(node *x) { node *y, *z; while (x->pa) { y = x->pa; if (!y->pa) rotate(x); else { z = y->pa; if (z->lch == y && y -> lch == x || z->rch == y && y->rch == x) rotate(x), rotate(x); else rotate(y), rotate(x); } } return x; } node *Find(node *t, int id) { int s; while (true) { s = size(t->lch); if (s >= id) t = t->lch; else if (s + 1 == id) break; else t = t->rch, id -= s + 1; } return t; } node *Merge(node *x, node *y) { if (!x) return y; x = Find(x, size(x)); splay(x); x->rch = y; if (y) y->pa = x; update(x); return x; } pair Split(node *x, int idx) { if (!idx) return pair(0, x); if (!(size(x) - idx)) return pair(x, 0); x = Find(x, idx), splay(x); node *y = x->rch; y->pa = x->rch = 0; update(x); return pair(x, y); } void Put_Front() { int X, Y; scanf("%d%d", &X, &Y), X ++, Y ++; pair a = Split(top, X - 1); pair b = Split(a.second, Y - X + 1); top = Merge(b.first, Merge(a.first, b.second)); } void Put_Back() { int X, Y; scanf("%d%d", &X, &Y), X ++, Y ++; pair a = Split(top, X - 1); pair b = Split(a.second, Y - X + 1); top = Merge(Merge(a.first, b.second), b.first); } char Query() { int idx; scanf("%d", &idx), idx ++; node *x = Find(top, idx); top = splay(x); return top->val; } int Q, opt; int main() { freopen("std.in", "r", stdin); freopen("Code.out", "w", stdout); scanf("%s", s); top = Build(s, strlen(s)); scanf("%d", &Q); while (Q --) { scanf("%d", &opt); if (opt == 1) Put_Front(); if (opt == 2) Put_Back(); if (opt == 3) printf("%c\n", Query()); } return 0; } 可持久化Treap-指针 /* Treap[Merge,Split] by Memphis */ #include<cstdio> #include<algorithm> #include<cstring> #include<ctime> using namespace std; #define maxn 2000005 #define rep(i,x,y) for(int i=x;i<=y;++i) #define dep(i,x,y) for(int i=x;i>=y;--i) struct Treap{ Treap *l,*r; int fix,key,size; Treap(int key_):fix(rand()),key(key_),l(NULL),r(NULL),size(1){} inline void updata(){ size=1+(l?l->size:0)+(r?r->size:0); } }*root; typedef pair<Treap*,Treap*> Droot;//用来Split返回两个根 inline int Size(Treap *x){return x?x->size:0;}//这样求size可以防止访问空指针 Treap *Merge(Treap *A,Treap *B){//合并操作 if(!A)return B; if(!B)return A; if(A->fix<B->fix){ A->r=Merge(A->r,B); A->updata(); return A; }else{ B->l=Merge(A,B->l); B->updata(); return B; } } Droot Split(Treap *x,int k){//拆分操作 if(!x)return Droot(NULL,NULL); Droot y; if(Size(x->l)>=k){ y=Split(x->l,k); x->l=y.second; x->updata(); y.second=x; }else{ y=Split(x->r,k-Size(x->l)-1); x->r=y.first; x->updata(); y.first=x; } return y; } Treap *Build(int *a){//建造操作 static Treap *stack[maxn],*x,*last; int p=0; rep(i,1,a[0]){ x=new Treap(a[i]); last=NULL; while(p && stack[p]->fix>x->fix){ stack[p]->updata(); last=stack[p]; stack[p--]=NULL; } if(p) stack[p]->r=x; x->l=last; stack[++p]=x; } while(p) stack[p--]->updata(); return stack[1]; } int Findkth(int k){//查找第K小 Droot x=Split(root,k-1); Droot y=Split(x.second,1); Treap *ans=y.first; root=Merge(Merge(x.first,ans),y.second); return ans->key; } int Getkth(Treap *x,int v){//询问一个数是第几大 if(!x)return 0; return v<x->key?Getkth(x->l,v):Getkth(x->r,v)+Size(x->l)+1; } void Insert(int v){//插入操作 int k=Getkth(root,v); Droot x=Split(root,k); Treap *n=new Treap(v); root=Merge(Merge(x.first,n),x.second); } void Delete(int k){//删除操作 Droot x=Split(root,k-1); Droot y=Split(x.second,1); root=Merge(x.first,y.second); } int a[maxn],M,x,y; int main(){ freopen("bst.in","r",stdin); freopen("bst.out","w",stdout); scanf("%d",a); rep(i,1,a[0]) scanf("%d",a+i); sort(a+1,a+1+a[0]); root=Build(a); scanf("%d",&M); while(M--){ char ch=getchar(); while(ch!='Q' && ch!='A' && ch!='D') ch=getchar(); scanf("%d",&x); if(ch=='Q') printf("%d\n",Findkth(x)); if(ch=='A') Insert(x); if(ch=='D') Delete(x); } } Treap //fan_hd #include <cstdio> #include <cstdlib> using namespace std; class Treap{ public: #define Max_N 1<<20 struct point{ int pri,val,father,left,right; point *left,*right; }p[Max_N]; int length; int rand_arr[Max_N]; void reset(int key){ srand(time(0)); for (int i=0;i!=key;rand_arr[i]=i++;) for (int i=0;i!=key;i++){ int a=rand()%key,b=rand()%key; rand_arr[a]^=rand_arr[b],rand_arr[b]^=rand_arr[a],rand_arr[a]^=rand_arr[b]; //swap } length=0; p[0].pri=-1; p[0].left=1; } inline void left_rotate(int now,int father){ int now_right=p[now].right; p[now].right=father,p[father].left=now_right; p[now].father^=p[father].father,p[father].father^=p[now].father,p[now].father^=p[father].father;//swap } inline void right_rotate(int now,int father){ int now_left=p[now].left; p[now].left=father,p[father].right=now_left; p[now].father^=p[father].father,p[father].father^=p[now].father,p[now].father^=p[father].father;//swap } void insert(int va,int pr){ p[++length]={pr,va,0,0,0}; if (length==1) return; for (int i=p[0].left,f;i;f=i,i=va>p[i].val?p[i].right:p[i].left); p[length].father=f; while (pr<p[p[length].father].pri){ if (p[p[length].father].left==length) left_rotate(length,p[length].father); else right_rotate(length,p[length].father); } } int find(int v){ for (int i=p[0].left;i;){ if (p[i].val==v) return i; else i=v>p[i].val?p[i].right:p[i].left; } return -1; } void del(int v){ int pos=find(v); if (pos+1==0) return; for(;;){ if (pos[i]) } } void print(){ } }; int main(){ return 0; } FWT #include<bits/stdc++.h> using namespace std; const int N=1e3+100,mod=1e9+7,rev=(mod+1)>>1; int a[N],ans[N]; void FWT(int *a,int n) { for(int d=1;d<n;d<<=1) for(int m=d<<1,i=0;i<n;i+=m) for(int j=0;j<d;j++) { int x=a[i+j],y=a[i+j+d]; a[i+j]=(x+y)%mod,a[i+j+d]=(x-y+mod)%mod; //xor:a[i+j]=x+y,a[i+j+d]=(x-y+mod)%mod; //and:a[i+j]=x+y; //or:a[i+j+d]=x+y; } } void UFWT(int *a,int n) { for(int d=1;d<n;d<<=1) for(int m=d<<1,i=0;i<n;i+=m) for(int j=0;j<d;j++) { int x=a[i+j],y=a[i+j+d]; a[i+j]=1LL*(x+y)*rev%mod,a[i+j+d]=(1LL*(x-y)*rev%mod+mod)%mod; //xor:a[i+j]=(x+y)/2,a[i+j+d]=(x-y)/2; //and:a[i+j]=x-y; //or:a[i+j+d]=y-x; } } void solve(int *a,int *b,int n) { FWT(a,n); FWT(b,n); for(int i=0;i<n;i++) a[i]=1LL*a[i]*b[i]%mod; UFWT(a,n); } FWT应用-CodeForces - 662C-FWTxor #include<cstdio> #include<cstring> #include<algorithm> using namespace std; typedef long long LL; const int maxn=1e5+5,maxm=(1<<20)+5; LL a[maxn],b[maxm],f[maxm],n,m; char s[maxn]; void FWT(LL *a,LL n) { for(int d=1;d<n;d<<=1) for(int m=d<<1,i=0;i<n;i+=m) for(int j=0;j<d;j++) { LL x=a[i+j],y=a[i+j+d]; a[i+j]=(x+y),a[i+j+d]=(x-y); } } void UFWT(LL *a,LL n) { for(int d=1;d<n;d<<=1) for(int m=d<<1,i=0;i<n;i+=m) for(int j=0;j<d;j++) { LL x=a[i+j],y=a[i+j+d]; a[i+j]=(x+y)/2,a[i+j+d]=(x-y)/2; } } void solve(LL *a,LL *b,LL n) { FWT(a,n); FWT(b,n); for(int i=0;i<n;i++) a[i]=a[i]*b[i]; UFWT(a,n); } inline int calc(int x) { int res=0; for(;x;x-=x&-x)res++; return res; } int main() { scanf("%lld%lld",&n,&m); for(int i=0;i<n;++i) { scanf("%s",s); for(int j=0;j<m;++j)a[j]|=(s[j]=='1')<<i; } LL tot=(1<<n); for(int i=0;i<m;++i)b[a[i]]++; for(int i=0;i<tot;++i) { LL res=calc(i); f[i]=min(res,n-res); } solve(f,b,tot); LL ans=1e18; for(int i=0;i<tot;++i)ans=min(ans,f[i]); printf("%lld\n",ans); return 0; }
转载请注明原文地址: https://www.6miu.com/read-24976.html

最新回复(0)