DaD3zZ’s 模板
对拍
#include<cstdio> #include<cstdlib> using namespace std; int main() { int sb=0; while(true) { printf("%d\n",++sb); system("data.exe > input.in"); //data是数据生成器,input是生成的数据 system("std.exe < input.in > std.out"); system("DaD3zZ.exe < input.in > DaD3zZ.out"); if(system("fc std.out DaD3zZ.out"))break; }//std和自己的,和数据生成器均不需要加freopen }
BeiYu的高精度
namespace BigNumber{ static const int BASE = 10000; static const int WIDTH = 4; struct Big { vector<int> s; Big( long long num = 0 ) { *this = num; } Big operator =( long long num ) { s.clear(); do { s.push_back( num % BASE ); num /= BASE; } while ( num > 0 ); return(*this); } Big operator =( const string & str ) { s.clear(); int x, len = (str.length() - 1) / WIDTH + 1; for ( int i = 0; i < len; i++ ) { int end = str.length() - i * WIDTH; int start = max( 0, end - WIDTH ); sscanf( str.substr( start, end - start ).c_str(), "%d", &x ); s.push_back( x ); } return(*this); } Big operator +( const Big & b ) const { Big c; c.s.clear(); for ( int i = 0, g = 0;; i++ ) { if ( g == 0 && i >= s.size() && i >= b.s.size() ) break; int x = g; if ( i < s.size() ) x += s[i]; if ( i < b.s.size() ) x += b.s[i]; c.s.push_back( x % BASE ); g = x / BASE; } return(c); } Big operator -( const Big & b ) const { Big c; c.s.clear(); int i, g, n = s.size(), m = b.s.size(); for ( i = 0, g = 0; i < n; i++ ) { int x = s[i] - g; if ( i < m ) x -= b.s[i]; if ( x >= 0 ) g = 0; else { g = 1; x += BASE; } c.s.push_back( x ); } i = c.s.size() - 1; while ( c.s[i] == 0 && i ) c.s.pop_back(), i--; return(c); } Big operator *( const Big &b ) const { Big c; int i, j, n = s.size(), m = b.s.size(), size = m + n; c.s.resize( size, 0 ); for ( i = 0; i < n; i++ ) for ( j = 0; j < m; j++ ) c.s[i + j] += s[i] * b.s[j]; for ( i = 0; i < size; i++ ) { c.s[i + 1] += c.s[i] / BASE; c.s[i] %= BASE; } i = size - 1; while ( c.s[i] == 0 && i ) c.s.pop_back(), i--; return(c); } Big operator /( const Big & b ) const { Big c, f = 0; int n = s.size(), i; c.s.resize( n, 0 ); for ( i = n - 1; i >= 0; i-- ) { f = f * BASE; f.s[0] = s[i]; while ( f >= b ) { f -= b; c.s[i]++; } } i = n - 1; while ( c.s[i] == 0 && i ) c.s.pop_back(), i--; return(c); } Big operator %( const Big &b ) const { Big r = *this / b; r = *this - r * b; return(r); } Big operator +=( const Big & b ) { *this = *this + b; return(*this); } Big operator -=( const Big & b ) { *this = *this - b; return(*this); } Big operator *=( const Big & b ) { *this = *this * b; return(*this); } Big operator /=( const Big & b ) { *this = *this / b; return(*this); } Big operator %=( const Big & b ) { *this = *this % b; return(*this); } bool operator <( const Big & b ) const { int n = s.size(), m = b.s.size(); if ( m > n ) return(1); if ( m < n ) return(0); for ( int i = s.size() - 1; i >= 0; i-- ) { if ( s[i] < b.s[i] ) return(1); if ( s[i] > b.s[i] ) return(0); } return(0); } bool operator >( const Big & b ) const { return(b < *this); } bool operator >=( const Big & b ) const { return(!(*this < b) ); } bool operator <=( const Big & b ) const { return(!(b < *this) ); } bool operator ==( const Big & b ) const { return(!(*this < b) && !(b < *this) ); } bool operator !=( const Big & b ) const { return( (*this < b) || (b < *this) ); } }; ostream & operator <<( ostream &out, const Big & x ) { out << x.s.back(); for ( int i = x.s.size() - 2; i >= 0; i-- ) { char buf[10]; sprintf( buf, "%04d", x.s[i] ); for ( int j = 0; j < strlen( buf ); j++ ) out << buf[j]; } return(out); } istream & operator >>( istream &in, Big & x ) { string s; if ( !(in >> s) ) return(in); x = s; return(in); } }using namespace BigNumber;
数据结构
李超线段树
//BZOJ-1568 #include<iostream> #include<cstdio> #include<cstring> #include<cmath> using namespace std; int read() { int x=0,f=1; char ch=getchar(); while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();} while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();} return x*f; } int N,M; struct LineNode { double k,b; int id; LineNode(int x0=0,int y0=0,int x1=0,int y1=0,int ID=0) { id=ID; if (x0==x1) k=0,b=max(y0,y1); else k=(double)(y0-y1)/(x0-x1),b=(double)y0-k*x0; } double getf(int x) {return k*x+b;} }; bool cmp(LineNode A,LineNode B,int x) { if (!A.id) return 1; return A.getf(x)!=B.getf(x)?A.getf(x)<B.getf(x):A.id<B.id; //比较值直线A,B在x的值,如果A<B返回1 } #define maxn 50010 LineNode tree[maxn<<2]; LineNode Query(int now,int l,int r,int x) { if (l==r) return tree[now]; int mid=(l+r)>>1; LineNode tmp; if (x<=mid) tmp=Query(now<<1,l,mid,x); else tmp=Query(now<<1|1,mid+1,r,x); return cmp(tree[now],tmp,x)?tmp:tree[now]; } void insert(int now,int l,int r,LineNode x) { if (!tree[now].id) tree[now]=x; if (cmp(tree[now],x,l)) swap(tree[now],x); if (l==r || tree[now].k==x.k) return; int mid=(l+r)>>1; double X=(tree[now].b-x.b)/(x.k-tree[now].k);//求交点,X为交点横坐标,判断下放区间 if (X<l || X>r) return; if (X<=mid) insert(now<<1,l,mid,tree[now]),tree[now]=x; else insert(now<<1|1,mid+1,r,x); } void Insert(int now,int l,int r,int L,int R,LineNode x) { if (L<=l && R>=r) {insert(now,l,r,x); return;} int mid=(l+r)>>1; if (L<=mid) Insert(now<<1,l,mid,L,R,x); if (R>mid) Insert(now<<1|1,mid+1,r,L,R,x); } int main() { M=read(); N=50000; char opt[15]; while (M--) { scanf("%s",opt); if (opt[0]=='P') { double K,B; scanf("%lf%lf",&K,&B); LineNode tmp; tmp.k=B; tmp.b=K-B; tmp.id=1; Insert(1,1,N,1,N,tmp); } int x; if (opt[0]=='Q') x=read(),printf("%lld\n",(long long)(Query(1,1,N,x).getf(x)/100+1e-8)); } return 0; }
左偏树
//BZOJ-1367 #include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<cstring> using namespace std; int read() { int x=0,f=1; char ch=getchar(); while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();} while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();} return x*f; } #define maxn 1000100 long long ans; int n,data[maxn],root[maxn],L[maxn],R[maxn],cnt[maxn],tot; struct LeftTreeNode { int sz,son[maxn][2],d[maxn],size[maxn],a[maxn]; // LeftTreeNode () // { // sz=0;memset(son,0,sizeof(son));memset(size,0,sizeof(size)); // memset(cnt,0,sizeof(cnt));memset(a,0,sizeof(a));memset(d,0,sizeof(d)); // } int Merge(int x,int y) { if (!x) return y; if (!y) return x; if (a[x]<a[y]) swap(x,y); son[x][1]=Merge(son[x][1],y); size[x]=size[son[x][0]]+size[son[x][1]]+1; if (d[son[x][1]]>d[son[x][0]]) swap(son[x][0],son[x][1]); d[x]=d[son[x][1]]+1; return x; } int Push(int x) { a[++sz]=x; size[sz]=1; son[sz][0]=son[sz][1]=d[sz]=0; return sz; } int Pop(int x) {return Merge(son[x][0],son[x][1]);} int Top(int x) {return a[x];} int Size(int x) {return size[x];} }LTHeap; int main() { n=read(); for (int i=1; i<=n; i++) data[i]=read()-i; for (int i=1; i<=n; i++) { tot++; root[tot]=LTHeap.Push(data[i]); cnt[tot]=1; L[tot]=R[tot]=i; while (tot>1 && LTHeap.Top(root[tot])<LTHeap.Top(root[tot-1])) { tot--; root[tot]=LTHeap.Merge(root[tot],root[tot+1]); cnt[tot]+=cnt[tot+1]; R[tot]=R[tot+1]; while (LTHeap.Size(root[tot])*2>cnt[tot]+1) root[tot]=LTHeap.Pop(root[tot]); } } for (int i=1; i<=tot; i++) for (int j=L[i],top=LTHeap.Top(root[i]); j<=R[i]; j++) ans+=abs(data[j]-top); printf("%lld\n",ans); return 0; }
树链剖分
//BZOJ-1984 #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; inline int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=10*x+ch-'0';ch=getchar();} return x*f; } #define maxn 400010 int id[maxn<<2],va[maxn<<2],uu[maxn],vv[maxn],ww[maxn]; int n;struct data{int next,to,w;}edge[maxn<<1];int head[maxn],cnt; void add(int u,int v,int w){cnt++;edge[cnt].w=w;edge[cnt].to=v;edge[cnt].next=head[u];head[u]=cnt;} void insert(int u,int v,int w){add(u,v,w); add(v,u,w);} //-------------------------------------------------------------------------------------- int deep[maxn],fa[maxn],son[maxn],size[maxn],pl[maxn],sz,pr[maxn],top[maxn],pre[maxn]; void dfs_1(int now) { size[now]=1; for (int i=head[now]; i; i=edge[i].next) if (edge[i].to!=fa[now]) { fa[edge[i].to]=now; deep[edge[i].to]=deep[now]+1; dfs_1(edge[i].to); if (size[son[now]]<size[edge[i].to]) son[now]=edge[i].to; size[now]+=size[edge[i].to]; } } void dfs_2(int now,int chain) { pl[now]=++sz; pre[sz]=now; top[now]=chain; if (son[now]) dfs_2(son[now],chain); for (int i=head[now]; i; i=edge[i].next) if (edge[i].to!=son[now] && edge[i].to!=fa[now]) dfs_2(edge[i].to,edge[i].to); pr[now]=sz; } //-------------------------------------------------------------------------------------- int tree[maxn<<2],delc[maxn<<2],dela[maxn<<2]; inline void update(int now){tree[now]=max(tree[now<<1],tree[now<<1|1]);} inline void pushdown(int now) { if (delc[now]!=-1) { int cc=delc[now]; delc[now]=-1; delc[now<<1]=cc; dela[now<<1]=0; tree[now<<1]=cc; delc[now<<1|1]=cc; dela[now<<1|1]=0; tree[now<<1|1]=cc; } if (dela[now]) { int aa=dela[now]; dela[now]=0; dela[now<<1]+=aa; tree[now<<1]+=aa; dela[now<<1|1]+=aa; tree[now<<1|1]+=aa; } } void build(int now,int l,int r) { delc[now]=-1; dela[now]=0; if (l==r) {tree[now]=va[l];return;} int mid=(l+r)>>1; build(now<<1,l,mid); build(now<<1|1,mid+1,r); update(now); } void point_change(int now,int l,int r,int loc,int val) { if (l==r) {tree[now]=val;return;} int mid=(l+r)>>1;pushdown(now); if (loc<=mid) point_change(now<<1,l,mid,loc,val); else point_change(now<<1|1,mid+1,r,loc,val); update(now); } void segment_change(int now,int l,int r,int L,int R,int val) { if (L<=l && R>=r) {tree[now]=val;delc[now]=val;dela[now]=0;return;} int mid=(l+r)>>1;pushdown(now); if (L<=mid) segment_change(now<<1,l,mid,L,R,val); if (R>mid) segment_change(now<<1|1,mid+1,r,L,R,val); update(now); } void segment_add(int now,int l,int r,int L,int R,int val) { if (L<=l && R>=r) {tree[now]+=val;dela[now]+=val;return;} int mid=(l+r)>>1;pushdown(now); if (L<=mid) segment_add(now<<1,l,mid,L,R,val); if (R>mid) segment_add(now<<1|1,mid+1,r,L,R,val); update(now); } int segment_ask(int now,int l,int r,int L,int R) { if (L<=l && R>=r) return tree[now]; int mid=(l+r)>>1; int ans=0;pushdown(now); if (L<=mid) ans=max(segment_ask(now<<1,l,mid,L,R),ans); if (R>mid) ans=max(ans,segment_ask(now<<1|1,mid+1,r,L,R)); return ans; } //-------------------------------------------------------------------------------------- void Change(int x,int val) { point_change(1,1,n,pl[id[x]],val); } void Cover(int x,int y,int val) { while (top[x]!=top[y]) { if (deep[top[x]]<deep[top[y]]) swap(x,y); segment_change(1,1,n,pl[top[x]],pl[x],val); x=fa[top[x]]; } if (deep[x]>deep[y]) swap(x,y); if (x!=y) segment_change(1,1,n,pl[x]+1,pl[y],val);//这是有别于平常的判断 } void Add(int x,int y,int val) { while (top[x]!=top[y]) { if (deep[top[x]]<deep[top[y]]) swap(x,y); segment_add(1,1,n,pl[top[x]],pl[x],val); x=fa[top[x]]; } if (deep[x]>deep[y]) swap(x,y); if (x!=y) segment_add(1,1,n,pl[x]+1,pl[y],val); } void Max(int x,int y) { int ans=0; while (top[x]!=top[y]) { if (deep[top[x]]<deep[top[y]]) swap(x,y); ans=max(ans,segment_ask(1,1,n,pl[top[x]],pl[x])); x=fa[top[x]]; } if (deep[x]>deep[y]) swap(x,y); if (x!=y) ans=max(ans,segment_ask(1,1,n,pl[x]+1,pl[y])); printf("%d\n",ans); } //-------------------------------------------------------------------------------------- int main() { // freopen("msn.in","r",stdin); // freopen("msn.out","w",stdout); n=read(); for (int i=1; i<=n-1; i++) uu[i]=read(),vv[i]=read(),ww[i]=read(),insert(uu[i],vv[i],ww[i]); dfs_1(1); dfs_2(1,1); for (int i=1; i<=n-1; i++) if (deep[uu[i]]<deep[vv[i]]) id[i]=vv[i]; else id[i]=uu[i]; for (int i=1; i<=n-1; i++) va[pl[id[i]]]=ww[i];//边权下放至点,记录所下放的点的id build(1,1,n); while (true) { char opt[10]; scanf("%s",opt);if(opt[1]=='t')break; int u=read(),v=read(),w; switch (opt[1]) { case 'a': Max(u,v);break; case 'o': w=read();Cover(u,v,w);break; case 'd': w=read();Add(u,v,w);break; case 'h': Change(u,v);break; } } return 0; }
LinkCutTree
//BZOJ-2594 #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; inline int read() { int x=0,f=1; char ch=getchar(); while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();} while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();} return x*f; } #define N 100010 #define M 1000010 #define Q 100010 int n,m,q,num=0; int fa[N+M],son[N+M][2],s[N+M],val[N+M],maxx[N+M]; bool rev[N+M]; //init int father[N]; inline void init(){for (int i=1; i<=n; i++) father[i]=i;} inline int find(int x){if (x==father[x]) return x; return father[x]=find(father[x]);} inline void merge(int x,int y) {int fx=find(x),fy=find(y); if (fx!=fy) father[fx]=fy,num++;} //bing cha ji inline bool is_root(int x){return !fa[x] || son[fa[x]][1]!=x&& son[fa[x]][0]!=x;} inline void rev1(int x){if (!x)return; swap(son[x][0],son[x][1]);rev[x]^=1;} inline void pb(int x){if (rev[x]) rev1(son[x][0]),rev1(son[x][1]),rev[x]=0;} inline void update(int x) { maxx[x]=x; if (son[x][0]&&val[maxx[x]]<val[maxx[son[x][0]]]) maxx[x]=maxx[son[x][0]]; if (son[x][1]&&val[maxx[x]]<val[maxx[son[x][1]]]) maxx[x]=maxx[son[x][1]]; } inline void rotate(int x) { int y=fa[x],w=son[y][1]==x;son[y][w]=son[x][w^1]; if (son[x][w^1]) fa[son[x][w^1]]=y; if (fa[y]) { int z=fa[y];if (son[z][0]==y) son[z][0]=x; else if (son[z][1]==y) son[z][1]=x; } fa[x]=fa[y]; fa[y]=x; son[x][w^1]=y; update(y); } inline void splay(int x) { int top=1,i=x,y; s[1]=i; while (!is_root(i)) s[++top]=i=fa[i]; while (top) pb(s[top--]); while (!is_root(x)) { y=fa[x]; if (!is_root(y)) if ((son[fa[y]][0]==y)^(son[y][0]==x)) rotate(x);else rotate(y); rotate(x); } update(x); } inline void access(int x){for (int y=0; x; y=x,x=fa[x])splay(x),son[x][1]=y,update(x);} inline void makeroot(int x){access(x),splay(x),rev1(x);} inline void link(int x,int y){makeroot(x); fa[x]=y; access(x);} inline void cutf(int x){access(x),splay(x);fa[son[x][0]]=0; son[x][0]=0; update(x);} inline void cut(int x,int y){makeroot(x); cutf(y);} inline int request(int x,int y){makeroot(x); access(y); splay(y); return maxx[y];} //Link-Cut-Tree struct data{int from,to,tim,id;bool f;}road[M]; struct dat{int opt,a,b,id,ans;}ask[Q]; inline void swap(int &a,int &b) {int tmp=a; a=b; b=tmp;} inline int erfind(int u,int v) { int l=1,r=m; while (l<=r) { int mid=(l+r)>>1; if (road[mid].from==u && road[mid].from==v) return mid; if (road[mid].from<u) l=mid+1; else if (road[mid].from==u && road[mid].to<v) l=mid+1; else r=mid-1; } return l; } inline bool cmp1(data A,data B){if (A.from==B.from) return A.to<B.to; return A.from<B.from;} inline bool cmp2(data A,data B){return A.tim<B.tim;} inline bool cmp3(data A,data B){return A.id<B.id;} //prework int main() { // freopen("tube9.in","r",stdin); // freopen("tube.out","w",stdout); n=read(),m=read(),q=read(); for (int i=1; i<=m; i++) { road[i].from=read(),road[i].to=read(),road[i].tim=read(); if (road[i].from>road[i].to) swap(road[i].from,road[i].to); } sort(road+1,road+m+1,cmp2); //puts("1st OK"); for (int i=1; i<=m; i++) road[i].id=i,val[n+i]=road[i].tim,maxx[n+i]=n+i; sort(road+1,road+m+1,cmp1); for (int i=1; i<=q; i++) { ask[i].opt=read(),ask[i].a=read(),ask[i].b=read(); int tmp; if (ask[i].a>ask[i].b) swap(ask[i].a,ask[i].b); if (ask[i].opt==2) tmp=erfind(ask[i].a,ask[i].b),road[tmp].f=1,ask[i].id=road[tmp].id; } sort(road+1,road+m+1,cmp3); //puts("2ed OK"); //for (int i=1; i<=m; i++) //printf("%d %d %d %d !%d!\n",road[i].from,road[i].to,road[i].tim,road[i].id,road[i].f); init(); for (int i=1; i<=m; i++) if (!road[i].f) { if (find(road[i].from)!=find(road[i].to)) { merge(road[i].from,road[i].to); link(road[i].from,n+i); link(road[i].to,n+i); if (num==n-1) break; } } //printf("%d\n",num); //puts("3rd OK"); for (int i=q; i>0; i--) { //printf("%d is OK: %d\n",i,request(ask[i].a,ask[i].b)); if (ask[i].opt==1) ask[i].ans=val[request(ask[i].a,ask[i].b)]; else { int k=request(ask[i].a,ask[i].b); if (road[ask[i].id].tim<val[k]) cut(road[k-n].from,k),cut(road[k-n].to,k), link(ask[i].a,n+ask[i].id),link(ask[i].b,n+ask[i].id); } //puts("ABCDEFGHI"); } //puts("4th OK"); for (int i=1; i<=q; i++) if (ask[i].opt==1) printf("%d\n",ask[i].ans); return 0; }
KD-Tree
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; int read() { int x=0,f=1; char ch=getchar(); while (ch<'0' || ch>'9') {if (ch=='-')f=-1; ch=getchar();} while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();} return x*f; } #define inf 0x7fffffff #define maxn 500010 int n,D,ans; struct PointNode { int l,r; int d[2],maxx[2],minn[2]; PointNode (int x=0,int y=0) {l=r=0; d[0]=x,d[1]=y;} bool operator < (const PointNode & A) const {return d[D]<A.d[D];} }p[maxn]; int dis(PointNode A,PointNode B) {return abs(A.d[1]-B.d[1])+abs(A.d[0]-B.d[0]);} struct KDTreeNode { PointNode tree[maxn<<1],Point; int rt,ansMax,ansMin; void Update(int now) { for (int i=0; i<=1; i++) { tree[now].minn[i]=tree[now].maxx[i]=tree[now].d[i]; if (tree[now].l) tree[now].minn[i]=min(tree[tree[now].l].minn[i],tree[now].minn[i]), tree[now].maxx[i]=max(tree[tree[now].l].maxx[i],tree[now].maxx[i]); if (tree[now].r) tree[now].minn[i]=min(tree[tree[now].r].minn[i],tree[now].minn[i]), tree[now].maxx[i]=max(tree[tree[now].r].maxx[i],tree[now].maxx[i]); } } int BuildTree(int l,int r,int dd) { int mid=(l+r)>>1; D=dd; nth_element(p+l,p+mid,p+r+1); tree[mid]=p[mid]; for (int i=0; i<=1; i++) tree[mid].minn[i]=tree[mid].maxx[i]=tree[mid].d[i]; if (l<mid) tree[mid].l=BuildTree(l,mid-1,dd^1); if (r>mid) tree[mid].r=BuildTree(mid+1,r,dd^1); Update(mid); return mid; } int disMax(int now) { if (!now) return -inf; int re=0; for (int i=0; i<=1; i++) re+=max(abs(tree[now].maxx[i]-Point.d[i]),abs(tree[now].minn[i]-Point.d[i])); return re; } int disMin(int now) { if (!now) return inf; int re=0; for (int i=0; i<=1; i++) re+=max(0,tree[now].minn[i]-Point.d[i]); for (int i=0; i<=1; i++) re+=max(0,Point.d[i]-tree[now].maxx[i]); return re; } void GetMax(int now) { if (!now) return; int dl,dr,d0; d0=dis(tree[now],Point); ansMax=max(d0,ansMax); if (tree[now].l) dl=disMax(tree[now].l); if (tree[now].r) dr=disMax(tree[now].r); if (dl>dr) { if (dl>ansMax) GetMax(tree[now].l); if (dr>ansMax) GetMax(tree[now].r); } else { if (dr>ansMax) GetMax(tree[now].r); if (dl>ansMax) GetMax(tree[now].l); } } void GetMin(int now) { if (!now) return; int dl,dr,d0; d0=dis(tree[now],Point); if (d0) ansMin=min(ansMin,d0); if (tree[now].l) dl=disMin(tree[now].l); if (tree[now].r) dr=disMin(tree[now].r); if (dl<dr) { if (dl<ansMin) GetMin(tree[now].l); if (dr<ansMin) GetMin(tree[now].r); } else { if (dr<ansMin) GetMin(tree[now].r); if (dl<ansMin) GetMin(tree[now].l); } } int QueryMax(PointNode P) {Point=P; ansMax=-inf; GetMax(rt); return ansMax;} int QueryMin(PointNode P) {Point=P; ansMin=inf; GetMin(rt); return ansMin;} }KDTree; int main() { n=read(); for (int x,y,i=1; i<=n; i++) x=read(),y=read(),p[i].d[0]=x,p[i].d[1]=y; for (int i=0; i<=1; i++) p[0].maxx[i]=-inf,p[0].minn[i]=inf; KDTree.rt=KDTree.BuildTree(1,n,1); ans=inf; for (int i=1; i<=n; i++) { int minn=KDTree.QueryMin(p[i]),maxx=KDTree.QueryMax(p[i]); ans=min(ans,maxx-minn); } printf("%d\n",ans); return 0; }
Splay
#include<iostream> #include<cstdio> #include<cmath> #include<algorithm> #include<cstring> #include<stack> using namespace std; inline int read() { int x=0; char ch=getchar(); while (ch<'0' || ch>'9') {ch=getchar();} while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();} return x; } #define LL long long #define MAXN 200010 int N,M,power[MAXN],val[MAXN]; struct EdgeNode{int next,to,d;}edge[MAXN<<1]; int head[MAXN],cnt=1; inline void AddEdge(int u,int v) {cnt++; edge[cnt].next=head[u]; head[u]=cnt; edge[cnt].to=v;} inline void InsertEdge(int u,int v) {AddEdge(u,v); AddEdge(v,u);} int pl[MAXN],dfn,pr[MAXN],pre[MAXN],del[MAXN]; void DFS(int now,int last) { pl[now]=++dfn; pre[dfn]=now; del[dfn]=1; for (int i=head[now]; i; i=edge[i].next) if (edge[i].to!=last) DFS(edge[i].to,now); pr[now]=++dfn; del[dfn]=-1; } namespace SplayTree { int fa[MAXN],son[MAXN][2],sz,root,ln[MAXN],rn[MAXN],pos[MAXN]; LL sum[MAXN],tag[MAXN]; //ln记录左的数量,rn记录右的数量,tag标记 #define ls(x) son[x][0] #define rs(x) son[x][1] #define INF 1000100 inline void Update(int now) { sum[now]=sum[ls(now)]+sum[rs(now)]+(LL)val[now]; ln[now]=ln[ls(now)]+ln[rs(now)]+(del[now]==1); rn[now]=rn[ls(now)]+rn[rs(now)]+(del[now]==-1); } inline void paint(int now,LL D) {if (now) val[now]+=D*del[now],sum[now]+=D*(ln[now]-rn[now]),tag[now]+=D;} inline void PushDown(int now) { if (!tag[now]) return; LL D=tag[now]; tag[now]=0; if (ls(now)) paint(ls(now),D); if (rs(now)) paint(rs(now),D); } void print(int now) { PushDown(now); if (val[now]!=INF && val[now]!=-INF) printf("ID=%d ---%d [%d %d] %d %I64d %d %d %d %I64d\n", now,fa[now],ls(now),rs(now),val[now],sum[now],ln[now],rn[now],del[now],tag[now]); if (son[now][0]) print(son[now][0]); if (son[now][1]) print(son[now][1]); } inline bool Right(int now) {return son[fa[now]][1]==now;} inline void rotate(int now) { PushDown(fa[now]); PushDown(now); int f=fa[now],gf=fa[f],wh=Right(now); son[f][wh]=son[now][wh^1]; fa[son[f][wh]]=f; fa[f]=now; son[now][wh^1]=f; fa[now]=gf; if (gf) son[gf][son[gf][1]==f]=now; Update(f); Update(now); } inline void splay(int now,int tar) { for (int f; (f=fa[now])!=tar; rotate(now)) if (fa[f]!=tar) rotate(Right(now)==Right(f)? f:now); if (!tar) root=now; } inline int fmin(int x) {while (son[x][0]) x=son[x][0]; return x;} inline int fmax(int x) {while (son[x][1]) x=son[x][1]; return x;} inline void Split(int l,int r) { splay(l,0); int x=fmax(ls(root)); splay(r,0); int y=fmin(rs(root)); splay(x,0); splay(y,x); } inline LL Query(int pos) {Split(pl[1],pl[pos]); return sum[ls(rs(root))];} inline void Change(int x,int D) { Split(pl[x],pr[x]); int rt=son[rs(root)][0]; sum[rt]+=(LL)(ln[rt]-rn[rt])*D; val[rt]+=D*del[rt]; tag[rt]+=D; Update(rs(root)); Update(root); } inline void BuildTree(int l,int r,int last) { if (r<l) return; int mid=(l+r)>>1,now=mid; fa[now]=last; son[last][now>last]=now; if (l==r) {sum[now]=val[now]; ln[now]=del[now]==1; rn[now]=1-ln[now]; return;} BuildTree(l,mid-1,now); BuildTree(mid+1,r,now); Update(now); } inline void Init() {BuildTree(1,(N<<1)+2,0); root=(1+(N<<1)+2)>>1;} inline void MakeRoot(int now,int father) { Split(pl[now],pr[now]); int rt=ls(rs(root)); fa[ls(rs(root))]=0; son[rs(root)][0]=0; Update(rs(root)),Update(root); splay(pl[father],0); splay(fmin(rs(root)),root); son[rs(root)][0]=rt; fa[rt]=rs(root); Update(rs(root)),Update(root); } } using namespace SplayTree; int main() { N=read(); for (int i=2; i<=N; i++) InsertEdge(i,read()); dfn=1; DFS(1,0); for (int i=1; i<=N; i++) power[i]=read(); // for (int i=1; i<=N; i++) printf("id=%d [%d , %d]\n",pre[i],pl[pre[i]],pr[pre[i]]); for (int i=1; i<=N; i++) val[pl[i]]+=power[i],val[pr[i]]-=power[i]; // for (int i=1; i<=dfn; i++) printf("%d ",val[i]); puts(""); M=read(); SplayTree::Init(); while (M--) { // print(root); char opt[5]; scanf("%s",opt); int x,y; if (opt[0]=='Q') x=read(),printf("%I64d\n",SplayTree::Query(x)); if (opt[0]=='C') x=read(),y=read(),SplayTree::MakeRoot(x,y); if (opt[0]=='F') x=read(),y=read(),SplayTree::Change(x,y); } return 0; }
主席树 不带修&带修
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; int read() { int x=0,f=1; char ch=getchar(); while (ch<'0' || ch>'9') {if (ch=='-')f=-1; ch=getchar();} while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();} return x*f; } #define maxn 100100 #define maxm 500100 int n,m,q; int hh[maxn],ls[maxn]; int steck[maxn<<2],top; struct data{ int from,to,hard; bool operator < (const data& A) const {return hard<A.hard;} }road[maxm]; struct dat{int next,to;}edge[maxn<<1];int head[maxn<<1],cnt; void add(int u,int v){cnt++;edge[cnt].next=head[u];head[u]=cnt;edge[cnt].to=v;} int fa[maxn<<1],va[maxn<<1]; void init(){for (int i=1; i<=n*2; i++) fa[i]=i;} int find(int x) {if (x==fa[x]) return x; return fa[x]=find(fa[x]);} void Kruskal() { init(); int zz=n; sort(road+1,road+m+1); for (int i=1; i<=m; i++) { int u=road[i].from,v=road[i].to,w=road[i].hard; int fa1=find(u),fa2=find(v); if (fa1!=fa2) { zz++; fa[fa1]=fa[fa2]=zz; va[zz]=w; add(zz,fa2);add(zz,fa1); if (zz==2*n-1) break; } } } bool visit[maxn<<1];int father[maxn<<1][20],maxx[maxn<<1][20],deep[maxn<<1]; void dfs(int x) { visit[x]=1; steck[++top]=x; for (int i=1; i<20; i++) if (deep[x]>=(1<<i)) father[x][i]=father[father[x][i-1]][i-1], maxx[x][i]=max(maxx[x][i-1],maxx[father[x][i-1]][i-1]); else break; for (int i=head[x]; i; i=edge[i].next) { deep[edge[i].to]=deep[x]+1; maxx[edge[i].to][0]=va[x]; father[edge[i].to][0]=x; dfs(edge[i].to); } if (x>n) steck[++top]=x; } int sum[maxn*20],ll[maxn*20],rr[maxn*20],root[maxn<<2],sz; void insert(int l,int r,int &now,int fat,int val) { now=++sz; sum[now]=sum[fat]+1; if (l==r) return; ll[now]=ll[fat],rr[now]=rr[fat]; int mid=(l+r)>>1; if (val<=mid) insert(l,mid,ll[now],ll[fat],val); else insert(mid+1,r,rr[now],rr[fat],val); } int query(int l,int r,int L,int R,int kth) { if (l==r) return l; int mid=(l+r)>>1; if (sum[ll[R]]-sum[ll[L]]>=kth) return query(l,mid,ll[L],ll[R],kth); else return query(mid+1,r,rr[L],rr[R],kth-sum[ll[R]]+sum[ll[L]]); } int st[maxn<<2],ed[maxn<<2]; void prework() { for (int i=1; i<=n; i++) if (!visit[i]) dfs(find(i)); for (int i=1; i<=top; i++) { int tmp=steck[i]; if (tmp<=n) insert(1,n,root[i],root[i-1],hh[tmp]); else { root[i]=root[i-1]; if (!st[tmp]) st[tmp]=i; else ed[tmp]=i; } } } int search(int x,int val) { for(int i=19;i>=0;i--) if(deep[x]>=(1<<i) && maxx[x][i]<=val) x=father[x][i]; return x; } int main() { n=read(),m=read(),q=read(); for (int i=1; i<=n; i++) hh[i]=read(),ls[i]=hh[i]; sort(ls+1,ls+n+1); for (int i=1; i<=n; i++) hh[i]=lower_bound(ls+1,ls+n+1,hh[i])-ls; for (int i=1; i<=m; i++) road[i].from=read(),road[i].to=read(),road[i].hard=read(); Kruskal(); prework(); int lastans=-1,ans; for (int i=1; i<=q; i++) { int v=read(),x=read(),k=read(); if (lastans!=-1) v^=lastans,x^=lastans,k^=lastans; int tmp=search(v,x); int a=root[st[tmp]],b=root[ed[tmp]]; if (sum[b]-sum[a]<k) ans=-1; else ans=ls[query(1,n,a,b,sum[b]-sum[a]-k+1)]; printf("%d\n",ans); lastans=ans; } return 0; }
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<vector> using namespace std; inline int read() { int x=0,f=1; char ch=getchar(); while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();} while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();} return x*f; } #define MAXN 100010 #define vec vector<int> int N,Q,ls[MAXN<<1],tp,val[MAXN]; struct QNode{int x,y,z,opt;}q[MAXN]; struct EdgeNode{int next,to;}edge[MAXN<<1]; int head[MAXN],cnt=1; inline void AddEdge(int u,int v) {cnt++; edge[cnt].next=head[u]; head[u]=cnt; edge[cnt].to=v;} inline void InsertEdge(int u,int v) {AddEdge(u,v); AddEdge(v,u);} int pl[MAXN],dfn,pr[MAXN],deep[MAXN],father[17][MAXN]; inline void DFS(int now,int last) { pl[now]=++dfn; for (int i=1; i<=16; i++) if (deep[now]>=(1<<i)) father[i][now]=father[i-1][father[i-1][now]]; else break; for (int i=head[now]; i; i=edge[i].next) if (edge[i].to!=last) father[0][edge[i].to]=now,deep[edge[i].to]=deep[now]+1, DFS(edge[i].to,now); pr[now]=dfn; } inline int LCA(int x,int y) { if (deep[x]<deep[y]) swap(x,y); int dd=deep[x]-deep[y]; for (int i=0; i<=16; i++) if (dd&(1<<i)) x=father[i][x]; for (int i=16; i>=0; i--) if (father[i][x]!=father[i][y]) x=father[i][x],y=father[i][y]; return x==y? x:father[0][x]; } namespace PrTree { int lson[MAXN*80],rson[MAXN*80],sum[MAXN*80],sz,root[MAXN]; vec add,sub; inline void Insert(int l,int r,int &now,int fa,int pos,int val) { now=++sz; sum[now]=sum[fa]+val; if (l==r) {return;} lson[now]=lson[fa],rson[now]=rson[fa]; int mid=(l+r)>>1; if (pos<=mid) Insert(l,mid,lson[now],lson[fa],pos,val); else Insert(mid+1,r,rson[now],rson[fa],pos,val); } inline int Query(int l,int r,int kth) { if (l==r) return l; int mid=(l+r)>>1,sn=0,sr=0; for (int i=0; i<add.size(); i++) sr+=sum[rson[add[i]]],sn+=sum[add[i]]; for (int i=0; i<sub.size(); i++) sr-=sum[rson[sub[i]]],sn-=sum[sub[i]]; if (sn<kth) return -1; if (kth>sr) { for (int i=0; i<add.size(); i++) add[i]=lson[add[i]]; for (int i=0; i<sub.size(); i++) sub[i]=lson[sub[i]]; Query(l,mid,kth-sr); } else { for (int i=0; i<add.size(); i++) add[i]=rson[add[i]]; for (int i=0; i<sub.size(); i++) sub[i]=rson[sub[i]]; Query(mid+1,r,kth); } } inline void BuildTree(int now,int last) { Insert(1,tp,root[now],root[last],val[now],1); for (int i=head[now]; i; i=edge[i].next) if (edge[i].to!=last) BuildTree(edge[i].to,now); } }using namespace PrTree; namespace BIT { int tree[MAXN]; inline int lowbit(int x) {return x&-x;} inline void Modify(int x,int pos,int D) { for (int i=x; i<=dfn; i+=lowbit(i)) Insert(1,tp,tree[i],tree[i],pos,D); } inline int Add(int x) { add.push_back(root[x]); for (int i=pl[x]; i; i-=lowbit(i)) add.push_back(tree[i]); } inline int Sub(int x) { sub.push_back(root[x]); for (int i=pl[x]; i; i-=lowbit(i)) sub.push_back(tree[i]); } inline void Clear() {add.clear(); sub.clear();} }using namespace BIT; int main() { N=read(); Q=read(); for (int i=1; i<=N; i++) val[i]=read(),ls[++tp]=val[i]; for (int i=1,x,y; i<=N-1; i++) x=read(),y=read(),InsertEdge(x,y); DFS(1,0); for (int i=1; i<=Q; i++) { q[i].opt=read(),q[i].x=read(),q[i].y=read(); if (q[i].opt) q[i].z=LCA(q[i].x,q[i].y); else ls[++tp]=q[i].y; } sort(ls+1,ls+tp+1); tp=unique(ls+1,ls+tp+1)-ls-1; for (int i=1; i<=N; i++) val[i]=lower_bound(ls+1,ls+tp+1,val[i])-ls; for (int i=1; i<=Q; i++) if (!q[i].opt) q[i].y=lower_bound(ls+1,ls+tp+1,q[i].y)-ls; BuildTree(1,0); for (int i=1; i<=Q; i++) { int opt=q[i].opt,x=q[i].x,y=q[i].y,z=q[i].z; if (!opt) Modify(pl[x],val[x],-1),Modify(pr[x]+1,val[x],1),Modify(pl[x],y,1),Modify(pr[x]+1,y,-1),val[x]=y; else { Clear(); Add(x); Add(y); Sub(z); Sub(father[0][z]); int ans=Query(1,tp,opt); if (ans==-1) puts("invalid request!"); else printf("%d\n",ls[ans]); } } return 0; }
块状链表
#include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<cstring> #include<queue> #include<ctime> using namespace std; #define LL long long int read() { int x=0,f=1; char ch=getchar(); while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();} while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();} return x*f; } #define MAXN 100010 int Bsize,N,Q,a[MAXN]; namespace BlockLists { #define BN 5010 struct BLNode{int next,data[1010],tag,tmp[1010],size,maxx,minn,del; LL sum; bool rev;}B[BN]; int start,ID; queue<int>trash; inline int New() {if (trash.empty()) return ++ID; int tmp=trash.front(); trash.pop(); return tmp;} inline void Del(int x) {trash.push(x); B[x].next=-1; B[x].size=B[x].maxx=B[x].minn=B[x].sum=B[x].tag=B[x].rev=B[x].del=0;} inline int GetP(int rk) {int p; for (p=start; ~B[p].next && rk>B[p].size; p=B[p].next) rk-=B[p].size; return p;} inline int GetK(int rk) {int p; for (p=start; ~B[p].next && rk>B[p].size; p=B[p].next) rk-=B[p].size; return rk;} inline void PushDown(int x) { int sz=B[x].size; if (B[x].del) {int del=B[x].del; B[x].del=0; for (int i=1; i<=sz; i++) B[x].data[i]=del; B[x].sum=sz*del;} if (B[x].rev) {reverse(B[x].data+1,B[x].data+sz+1); B[x].rev^=1;} if (B[x].tag) {int tag=B[x].tag; B[x].tag=0; for (int i=1; i<=sz; i++) B[x].data[i]+=tag; B[x].sum+=(LL)sz*tag;} } inline void Update(int x) { int sz=B[x].size; B[x].sum=0; for (int i=1; i<=sz; i++) B[x].sum+=B[x].data[i],B[x].tmp[i]=B[x].data[i]; sort(B[x].tmp+1,B[x].tmp+sz+1); B[x].minn=B[x].tmp[1],B[x].maxx=B[x].tmp[B[x].size]; } inline void Split(int pos,int rk) { PushDown(pos); int id=New(); for (int i=rk; i<=B[pos].size; i++) B[id].data[++B[id].size]=B[pos].data[i]; B[id].next=B[pos].next; B[pos].next=id; B[pos].size=max(rk-1,0); Update(id); Update(pos); } inline void Merge(int pos) { for ( ; ~pos; pos=B[pos].next) for (int suf=B[pos].next; ~suf && B[pos].size+B[suf].size<=Bsize; suf=B[suf].next) { PushDown(pos),PushDown(suf); for (int k=1; k<=B[suf].size; k++) B[pos].data[++B[pos].size]=B[suf].data[k]; B[pos].next=B[suf].next,Del(suf),Update(pos); } } inline void Insert(int s,int x) { int now=GetP(s+1),pos=GetK(s+1); Split(now,pos); B[now].data[++B[now].size]=x; Update(now); Merge(now); } inline void Delete(int s) { int now=GetP(s),pos=GetK(s); PushDown(now); for (int i=pos+1; i<=B[now].size; i++) B[now].data[i-1]=B[now].data[i]; B[now].size--; Update(now),Merge(now); } inline void Prework(int l,int r,int &x,int &y) { int now1=GetP(l),pos1=GetK(l); Split(now1,pos1); int now2=GetP(r+1),pos2=GetK(r+1); Split(now2,pos2); x=now1,y=GetP(r); } int st[MAXN]; inline void Rever(int l,int r) { int x,y,top=0; Prework(l,r,x,y); for (int i=B[x].next; ~i && i!=B[y].next; i=B[i].next) st[++top]=i,B[i].rev^=1; B[st[1]].next=B[y].next; for (int i=top; i>1; i--) B[st[i]].next=st[i-1]; B[x].next=y; Merge(x); } inline void Move(int l,int r,int k) { int x,y,z,tmp; Prework(l,r-k,x,z); Prework(r-k+1,r,z,y); tmp=B[x].next; B[x].next=B[z].next,B[z].next=B[y].next,B[y].next=tmp; Merge(x); } inline void Add(int l,int r,int D) { int x,y; Prework(l,r,x,y); for (int i=B[x].next; ~i && i!=B[y].next; i=B[i].next) B[i].sum+=(LL)B[i].size*D,B[i].tag+=D; Merge(x); } inline void Modify(int l,int r,int val) { int x,y; Prework(l,r,x,y); for (int i=B[x].next; ~i && i!=B[y].next; i=B[i].next) B[i].tag=0,B[i].del=val,B[i].sum=(LL)B[i].size*val; Merge(x); } inline LL GetSum(int l,int r) { int x,y; LL re=0; Prework(l,r,x,y); for (int i=B[x].next; ~i && i!=B[y].next; i=B[i].next) re+=B[i].sum; Merge(x); return re; } #define INF 0x7fffffff inline int GetRange(int l,int r) { int x,y,maxx=-INF,minn=INF; Prework(l,r,x,y); for (int i=B[x].next; ~i && i!=B[y].next; i=B[i].next) if (B[i].del) maxx=max(maxx,B[i].del+B[i].tag),minn=min(minn,B[i].del+B[i].tag); else maxx=max(maxx,B[i].maxx+B[i].tag),minn=min(minn,B[i].minn+B[i].tag); Merge(x); return maxx-minn; } inline int GetClose(int l,int r,int val) { int x,y,re=INF; Prework(l,r,x,y); for (int t,i=B[x].next; ~i && i!=B[y].next; i=B[i].next) if (B[i].del) re=min(re,abs(val-(B[i].del+B[i].tag))); else { t=lower_bound(B[i].tmp+1,B[i].tmp+B[i].size+1,val-B[i].tag)-B[i].tmp; if (t!=B[i].size+1) re=min(re,abs(B[i].tmp[t]+B[i].tag-val)); if (t!=1) re=min(re,abs(val-(B[i].tmp[t-1]+B[i].tag))); } Merge(x); return re; } inline int GetKth(int l,int r,int k) { int x,y,t=-INF; Prework(l,r,x,y); for (int i=B[x].next; ~i && i!=B[y].next; i=B[i].next) t=max(t,B[i].del? B[i].del+B[i].tag:B[i].maxx+B[i].tag); int L=0,R=t; while (L<R) { int mid=((L+R)>>1)+1,re=1; for (int i=B[x].next; ~i && i!=B[y].next; i=B[i].next) if (B[i].del) if (B[i].del+B[i].tag<mid) re+=B[i].size; else; else t=upper_bound(B[i].tmp+1,B[i].tmp+B[i].size+1,mid-1-B[i].tag)-B[i].tmp,re+=max(0,t-1); if (k>=re) L=mid; else R=mid-1; } Merge(x); return L; } inline int GetSmall(int l,int r,int val) { int x,y,re=0; Prework(l,r,x,y); for (int t,i=B[x].next; ~i && i!=B[y].next; i=B[i].next) if (B[i].del) if (B[i].del+B[i].tag<val) re+=B[i].size; else; else t=upper_bound(B[i].tmp+1,B[i].tmp+B[i].size+1,val-B[i].tag-1)-B[i].tmp,re+=t-1; Merge(x); return re; } inline void Init() {start=0; ID=0; B[0].next=-1; B[0].size=0;} } using namespace BlockLists; int main() { // freopen("data.in","r",stdin); // freopen("ORZJRY.out","w",stdout); int N=read(); Init(); for (int x,i=1; i<=N; i++) x=read(),Insert(i-1,x); Bsize=sqrt(N+(rand()%((int)sqrt(N))) ); Q=read(); while (Q--) { // puts("============================================="); int opt=read(); int x,y,k; // printf("%d :",opt); switch (opt) { case 1: x=read(),k=read(),Insert(x,k); break; case 2: x=read(); Delete(x); break; case 3: x=read(),y=read(); Rever(x,y); break; case 4: x=read(),y=read(),k=read(); Move(x,y,k); break; case 5: x=read(),y=read(),k=read(); Add(x,y,k); break; case 6: x=read(),y=read(),k=read(); Modify(x,y,k); break; case 7: x=read(),y=read(); printf("%lld\n",GetSum(x,y)); break; case 8: x=read(),y=read(); printf("%d\n",GetRange(x,y)); break; case 9: x=read(),y=read(),k=read(); printf("%d\n",GetClose(x,y,k)); break; case 10: x=read(),y=read(),k=read(); printf("%d\n",GetKth(x,y,k)); break; case 11: x=read(),y=read(),k=read(); printf("%d\n",GetSmall(x,y,k)); break; } // puts(""); } return 0; }
图论相关
网络流 最大流&费用流&zkw费用流&分治最小割
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> #include<queue> using namespace std; int read() { int x=0,f=1; char ch=getchar(); while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();} while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();} return x*f; } #define MAXN 1010 #define MAXM 1001010 int L,W,N; struct PointNode{int x,y;}P[MAXN]; struct EdgeNode{int next,to,cap;}edge[MAXM]; int head[MAXN],cnt=1; void AddEdge(int u,int v,int w) {cnt++; edge[cnt].next=head[u]; head[u]=cnt; edge[cnt].to=v; edge[cnt].cap=w;} void InsertEdge(int u,int v,int w) {AddEdge(u,v,w); AddEdge(v,u,0);} queue<int>q; int cur[MAXN],S,T,h[MAXN]; #define INF 0x7fffffff bool bfs() { queue<int>q; for (int i=S; i<=T; i++) h[i]=-1; h[S]=1; q.push(S); while (!q.empty()) { int now=q.front(); q.pop(); for (int i=head[now]; i; i=edge[i].next) if (h[edge[i].to]==-1 && edge[i].cap) h[edge[i].to]=h[now]+1,q.push(edge[i].to); } return h[T]!=-1; } int dfs(int loc,int low) { if (loc==T) return low; int used=0,w; for (int i=cur[loc]; i; i=edge[i].next) if (edge[i].cap && h[edge[i].to]==h[loc]+1) { w=dfs(edge[i].to,min(edge[i].cap,low-used)); edge[i].cap-=w; edge[i^1].cap+=w; used+=w; if (used==low) return low; if (edge[i].to) cur[loc]=i; } if (!used) h[loc]=-1; return used; } int Dinic() { int tmp=0; while (bfs()) { for (int i=S; i<=T; i++) cur[i]=head[i]; tmp+=dfs(S,INF); } return tmp; } int Dis(PointNode a,PointNode b) {return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));} int main() { L=read(),W=read(),N=read(); for (int x,y,i=1; i<=N; i++) P[i].x=read(),P[i].y=read(); S=0,T=2*N+1; for (int i=1; i<=N; i++) for (int j=1; j<=N; j++) if (Dis(P[i],P[j])<=200 && i!=j) InsertEdge(i+N,j,INF); for (int i=1; i<=N; i++) { if (P[i].y<=100) InsertEdge(S,i,INF); if (abs(W-P[i].y)<=100) InsertEdge(i+N,T,INF); InsertEdge(i,i+N,1); } printf("%d\n",Dinic()); return 0; }
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include<queue> using namespace std; int read() { int x=0,f=1; char ch=getchar(); while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();} while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();} return x*f; } #define maxp 1000 #define maxn 100010 #define maxm 1000010 int n,m,S,T,ans,tot;int p[maxp],tt[maxp][maxp]; struct data{int from,next,to,cap,cost;}edge[maxm<<2]; int head[maxn],from[maxn],cnt=1; void add(int u,int v,int w,int c) {cnt++;edge[cnt].from=u;edge[cnt].to=v; edge[cnt].next=head[u];head[u]=cnt; edge[cnt].cost=c;edge[cnt].cap=w;} void insert(int u,int v,int w,int c){add(u,v,w,c);add(v,u,0,-c);} #define inf 0x7fffffff bool visit[maxn];int dis[maxn]; bool spfa() { queue<int>q; for (int i=S; i<=T; i++) dis[i]=inf; q.push(S); visit[S]=1; dis[S]=0; while (!q.empty()) { int now=q.front(); q.pop(); for (int i=head[now]; i; i=edge[i].next) if (edge[i].cap && dis[now]+edge[i].cost<dis[edge[i].to]) { dis[edge[i].to]=dis[now]+edge[i].cost; from[edge[i].to]=i; if (!visit[edge[i].to]) q.push(edge[i].to),visit[edge[i].to]=1; } visit[now]=0; } return dis[T]!=inf; } void MinCostMaxFlow() { int flow=inf,a,b,x; for (int i=from[T]; i; i=from[edge[i].from]) { flow=min(flow,edge[i].cap); if (!edge[i].from) x=edge[i].to,a=(x-1)/tot+1,b=x%tot+1; } for (int i=from[T]; i; i=from[edge[i].from]) edge[i].cap-=flow,edge[i^1].cap+=flow,ans+=edge[i].cost*flow; for (int i=1; i<=n; i++) insert((a-1)*tot+b,m*tot+i,1,b*tt[i][a]); } void make() { S=0,T=100001; for (int i=1; i<=tot*m; i++) insert(S,i,1,0); for (int i=1; i<=n; i++) insert(m*tot+i,T,p[i],0); for (int i=1; i<=m; i++) for (int j=1; j<=n; j++) insert((i-1)*tot+1,m*tot+j,1,tt[j][i]); } int main() { n=read(),m=read(); for (int i=1; i<=n; i++) p[i]=read(),tot+=p[i]; for (int i=1; i<=n; i++) for (int j=1; j<=m; j++) tt[i][j]=read(); make(); while (spfa()) MinCostMaxFlow(); printf("%d\n",ans); return 0; }
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include<queue> using namespace std; inline int read() { int x=0,f=1; char ch=getchar(); while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();} while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();} return x*f; } #define MAXN 11000 #define MAXM 500010 #define INF 0x7fffffff int N,mp[110][110],id[110][110],e[10100][110]; struct EdgeNode{int next,to,from,cap,cost;}edge[MAXM<<1]; int head[MAXN],cnt=1; inline void AddEdge(int u,int v,int w,int c) {cnt++; edge[cnt].next=head[u]; head[u]=cnt; edge[cnt].to=v; edge[cnt].from=u; edge[cnt].cost=c; edge[cnt].cap=w;} inline void InsertEdge(int u,int v,int w,int c) {AddEdge(u,v,w,c); AddEdge(v,u,0,-c);} int mark[MAXM],dis[MAXM],Flow,Cost,S,T; inline bool SPFA() { for (int i=S; i<=T; i++) dis[i]=INF,mark[i]=0; queue<int>q; q.push(S); dis[S]=0; mark[S]=1; while (!q.empty()) { int now=q.front(); q.pop(); mark[now]=0; for (int i=head[now]; i; i=edge[i].next) if (edge[i].cap && dis[edge[i].to]>dis[now]+edge[i].cost) { dis[edge[i].to]=dis[now]+edge[i].cost; if (!mark[edge[i].to]) q.push(edge[i].to),mark[edge[i].to]=1; } } return dis[T]!=INF; } inline int DFS(int loc,int low) { mark[loc]=1; if (loc==T) return low; int used=0,w; for (int i=head[loc]; i; i=edge[i].next) if (edge[i].cap && !mark[edge[i].to] && dis[edge[i].to]==dis[loc]+edge[i].cost) { w=DFS(edge[i].to,min(edge[i].cap,low-used)); edge[i].cap-=w; edge[i^1].cap+=w; used+=w; Cost+=w*edge[i].cost; if (low==used) return used; } return used; } inline int ZKW() { int re=0; while (SPFA()) { mark[T]=1; while (mark[T]) { for (int i=S; i<=T; i++) mark[i]=0; re+=DFS(S,INF); } } return re; } int main() { N=read(); for (int i=1; i<=N; i++) for (int j=1; j<=N; j++) mp[i][j]=read(); int ID=N; for (int i=1; i<=N; i++) for (int j=1; j<=N; j++) id[i][j]=++ID; S=0; T=ID+1; for (int i=1; i<=N; i++) for (int j=i+1; j<=N; j++) if (i!=j) { InsertEdge(S,id[i][j],1,0); switch (mp[i][j]) { case 1: InsertEdge(id[i][j],i,1,0); break; case 0: InsertEdge(id[i][j],j,1,0); break; case 2: InsertEdge(id[i][j],i,1,0); e[id[i][j]][i]=cnt-1; InsertEdge(id[i][j],j,1,0); e[id[i][j]][j]=cnt-1; break; } } for (int i=1; i<=N; i++) for (int j=1; j<=N; j++) InsertEdge(i,T,1,j-1); ZKW(); printf("%d\n",N*(N-2)*(N-1)/6-Cost); for (int i=1; i<=N; i++) for (int j=i+1; j<=N; j++) if (mp[i][j]==2) { mp[i][j]=edge[e[id[i][j]][i]].cap==0; mp[j][i]=mp[i][j]^1; } for (int i=1; i<=N; i++,puts("")) for (int j=1; j<=N; j++) printf("%d ",mp[i][j]); return 0; }
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> using namespace std; int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } #define maxn 200 #define maxm 100010 int n,m,q,t,ans[maxn][maxn],id[maxn],tmp[maxn]; struct Edgenode{int next,to,cap;}edge[maxm]; int head[maxn],cnt=1; void add(int u,int v,int w) {cnt++; edge[cnt].to=v; edge[cnt].next=head[u]; head[u]=cnt; edge[cnt].cap=w;} void insert(int u,int v,int w) {add(u,v,w); add(v,u,w);} int dis[maxn],que[maxn<<1],cur[maxn],S,T; bool bfs() { memset(dis,-1,sizeof(dis)); que[0]=S; dis[S]=0; int he=0,ta=1; while (he<ta) { int now=que[he++]; for (int i=head[now]; i; i=edge[i].next) if (edge[i].cap && dis[edge[i].to]==-1) dis[edge[i].to]=dis[now]+1,que[ta++]=edge[i].to; } return dis[T]!=-1; } int dfs(int loc,int low) { if (loc==T) return low; int w,used=0; for (int i=cur[loc]; i; i=edge[i].next) if (edge[i].cap && dis[edge[i].to]==dis[loc]+1) { w=dfs(edge[i].to,min(low-used,edge[i].cap)); edge[i].cap-=w; edge[i^1].cap+=w; used+=w; if (edge[i].cap) cur[loc]=i; if (used==low) return low; } if (!used) dis[loc]=-1; return used; } #define inf 0x7fffffff int dinic() { int tmp=0; while (bfs()) { for (int i=1; i<=n; i++) cur[i]=head[i]; tmp+=dfs(S,inf); } return tmp; } void init() { cnt=1; memset(ans,127,sizeof(ans)); memset(head,0,sizeof(head)); } bool visit[maxn]; void DFS(int x) { visit[x]=1; for (int i=head[x]; i; i=edge[i].next) if (edge[i].cap && !visit[edge[i].to]) DFS(edge[i].to); } void work(int L,int R) { if (L==R) return; for (int i=2; i<=cnt; i+=2) edge[i].cap=edge[i^1].cap=(edge[i].cap+edge[i^1].cap)>>1; S=id[L],T=id[R]; int maxflow=dinic(); memset(visit,0,sizeof(visit)); DFS(S); for (int i=1; i<=n; i++) if (visit[i]) for (int j=1; j<=n; j++) if (!visit[j]) ans[i][j]=ans[j][i]=min(ans[i][j],maxflow); int l=L,r=R; for (int i=L; i<=R; i++) if (visit[id[i]]) tmp[l++]=id[i]; else tmp[r--]=id[i]; for (int i=L; i<=R; i++) id[i]=tmp[i]; work(L,l-1); work(r+1,R); } int main() { // freopen("mincuto.in","r",stdin); // freopen("mincuto.out","w",stdout); t=read(); while (t--) { init(); n=read(),m=read(); for (int i=1; i<=n; i++) id[i]=i; for (int u,v,w,i=1; i<=m; i++) u=read(),v=read(),w=read(),insert(u,v,w); work(1,n); q=read(); for (int c,i=1; i<=q; i++) { c=read(); int an=0; for (int j=1; j<=n; j++) for (int k=j+1; k<=n; k++) if (ans[j][k]<=c) an++; printf("%d\n",an); } puts(""); } return 0; }
拓扑排序
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<vector> #include<queue> #include<stack> using namespace std; int read() { int x=0,f=1; char ch=getchar(); while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();} while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();} return x*f; } #define maxn 1000 #define maxm 1000010 int n,m,total,score[maxn]; struct EdgeNode{int next,to,cap;}edge[maxm]; int head[maxn],cnt=1; void addedge(int u,int v,int w) {cnt++; edge[cnt].next=head[u]; head[u]=cnt; edge[cnt].to=v; edge[cnt].cap=w;} void insertedge(int u,int v,int w) {addedge(u,v,w); addedge(v,u,0);} struct RoadNode{int next,to;}road[maxm>>1]; int last[maxn],tot; void addroad(int u,int v) {tot++; road[tot].next=last[u]; last[u]=tot; road[tot].to=v;} void insertroad(int u,int v) {addroad(u,v);} bool visit[maxn]; int du[maxn],s,t; void Paint(int now) { visit[now]=1; for (int i=last[now]; i; i=road[i].next) if (!visit[road[i].to]) Paint(road[i].to); } void TopoSort() { s=1,t=n*m; stack<int>st; for (int i=s; i<=t; i++) if (!du[i]) st.push(i); else visit[i]=1; while (!st.empty()) { int now=st.top(); st.pop(); visit[now]=0; for (int i=last[now]; i; i=road[i].next) { du[road[i].to]--; if (!du[road[i].to]) st.push(road[i].to); } //printf("%d\n",now); } for (int i=s; i<=t; i++) if (visit[i]) Paint(i); } int dis[maxn],cur[maxn],S,T; #define inf 0x7fffffff bool bfs() { queue<int>q; for (int i=S; i<=T; i++) dis[i]=-1; q.push(S); dis[S]=0; while (!q.empty()) { int now=q.front(); q.pop(); for (int i=head[now]; i; i=edge[i].next) if (edge[i].cap && dis[edge[i].to]==-1) dis[edge[i].to]=dis[now]+1,q.push(edge[i].to); } return dis[T]!=-1; } int dfs(int loc,int low) { if (loc==T) return low; int w,used=0; for (int i=cur[loc]; i; i=edge[i].next) if (edge[i].cap && dis[edge[i].to]==dis[loc]+1) { w=dfs(edge[i].to,min(low-used,edge[i].cap)); edge[i].cap-=w; edge[i^1].cap+=w; used+=w; if (used==low) return low; if (edge[i].cap) cur[loc]=i; } if (!used) dis[loc]=-1; return used; } int dinic() { int tmp=0; while (bfs()) { for (int i=S; i<=T; i++) cur[i]=head[i]; tmp+=dfs(S,inf); } return tmp; } void Build() { S=0,T=n*m+1; for (int i=1; i<=n*m; i++) if (!visit[i]) { if (score[i]>0) insertedge(i,T,score[i]); else insertedge(S,i,-score[i]); for (int j=last[i]; j; j=road[j].next) if (!visit[road[j].to]) insertedge(i,road[j].to,inf); total+=score[i]>0?score[i]:0; } } int locate(int x,int y) {return (x-1)*m+y;} int main() { n=read(),m=read(); for (int i=1; i<=n; i++) for (int j=1; j<=m; j++) { int now=locate(i,j),num; score[now]=read(); num=read(); for (int x,y,k=1; k<=num; k++) x=read()+1,y=read()+1,insertroad(now,locate(x,y)),du[locate(x,y)]++; if (j>1) insertroad(now,locate(i,j-1)),du[locate(i,j-1)]++; } TopoSort(); Build(); int maxflow=dinic();// printf("%d %d\n",total,maxflow); printf("%d\n",total-maxflow); return 0; }
Tarjan 强连通分量&双连通分量+割点
//BZOJ-1179 #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<queue> using namespace std; #define maxn 500010 int read() { int x=0,f=1; char ch=getchar(); while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();} while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();} return x*f; } int n,m,uu,S,P,ans,val[maxn]; struct Edgenode{int to,next,val;}edge[maxn<<1]; int head[maxn<<1],cnt=1; void add(int u,int v) {cnt++;edge[cnt].to=v;edge[cnt].next=head[u];head[u]=cnt;} struct Roadnode{int to,next;}road[maxn]; int last[maxn],cn=1; void insert(int u,int v) {cn++;road[cn].to=v;road[cn].next=last[u];last[u]=cn;} int dfn[maxn],low[maxn],qcnt,stack[maxn],top,num[maxn],belong[maxn],tot,valu[maxn]; bool visit[maxn]; void Tarjan(int x) { dfn[x]=low[x]=++tot; visit[x]=1; stack[++top]=x; for (int i=head[x]; i; i=edge[i].next) { if (!dfn[edge[i].to]) { Tarjan(edge[i].to); if (low[edge[i].to]<low[x]) low[x]=low[edge[i].to]; } else if(visit[edge[i].to] && dfn[edge[i].to]<low[x]) low[x]=dfn[edge[i].to]; } if (dfn[x]==low[x]) { qcnt++; while (x!=uu) uu=stack[top--],num[qcnt]++,visit[uu]=0,belong[uu]=qcnt,valu[qcnt]+=val[uu]; } } void rebuild() { for (int i=1; i<=n; i++) for (int j=head[i]; j; j=edge[j].next) if (belong[i]!=belong[edge[j].to]) insert(belong[i],belong[edge[j].to]); } #define inf 0x7fffffff int dis[maxn]; void spfa() { queue<int>que; memset(visit,0,sizeof(visit)); // for (int i=1; i<=qcnt; i++) dis[i]=-inf; visit[S]=1; dis[S]=valu[S]; que.push(S); while (!que.empty()) { int now=que.front(); que.pop(); visit[now]=0; for (int i=last[now]; i; i=road[i].next) if (dis[road[i].to]<dis[now]+valu[road[i].to]) { dis[road[i].to]=dis[now]+valu[road[i].to]; if (!visit[road[i].to]) visit[road[i].to]=1,que.push(road[i].to); } } } bool bar[maxn]; int main() { n=read(),m=read(); for (int u,v,i=1; i<=m; i++) u=read(),v=read(),add(u,v); for (int i=1; i<=n; i++) val[i]=read(); for (int i=1; i<=n; i++) if (!dfn[i]) Tarjan(i); S=read(); S=belong[S]; P=read(); for (int x,i=1; i<=P; i++) x=read(),bar[x]=1; rebuild(); spfa(); // for (int i=1; i<=n; i++) // printf("%d\n",dis[belong[i]]); for (int i=1; i<=n; i++) if (bar[i]) ans=max(ans,dis[belong[i]]); printf("%d\n",ans); return 0; }
//UOJ67 #include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<algorithm> #include<vector> using namespace std; #define LL long long inline int read() { int x=0,f=1; char ch=getchar(); while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();} while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();} return x*f; } #define MAXN 100010 int N,M,tot; LL sum; struct EdgeNode{int next,to,from;}edge[MAXN<<1]; int head[MAXN],cnt=1; void AddEdge(int u,int v) {cnt++; edge[cnt].next=head[u]; head[u]=cnt; edge[cnt].to=v;} void InsertEdge(int u,int v) {AddEdge(u,v); AddEdge(v,u);} #define Pa pair<int,int> vector<int>BCC[MAXN]; Pa st[MAXN]; int top; int dfn[MAXN],low[MAXN],dfsn,cut[MAXN],bcc,belong[MAXN],d[MAXN]; void Tarjan(int now,int last) { dfn[now]=low[now]=++dfsn; int son=0; for (int i=head[now]; i; i=edge[i].next) if (!dfn[edge[i].to]) { st[++top]=make_pair(now,edge[i].to); son++; Tarjan(edge[i].to,now); low[now]=min(low[now],low[edge[i].to]); if (dfn[now]<=low[edge[i].to]) { cut[now]=1; bcc++; BCC[bcc].clear(); int tnow=-1,tto=-1; while (1) { tnow=st[top].first,tto=st[top].second; top--; if (belong[tnow]!=bcc) BCC[bcc].push_back(tnow),belong[tnow]=bcc; if (belong[tto]!=bcc) BCC[bcc].push_back(tto),belong[tto]=bcc; if (tnow==now && tto==edge[i].to) break; } } } else if (dfn[edge[i].to]<dfn[now] && edge[i].to!=last) st[++top]=make_pair(now,edge[i].to),low[now]=min(low[now],dfn[edge[i].to]); if (last<0 && son==1) cut[now]=0; } int main() { N=read(),M=read(); for (int x,y,i=1; i<=M; i++) x=read(),y=read(),InsertEdge(x,y),d[x]++,d[y]++; for (int i=1; i<=N; i++) if (!dfn[i]) Tarjan(i,-1); for (int i=1; i<=N; i++) if (!cut[i] && d[i]==M-N+2) tot++; printf("%d\n",tot); for (int i=1; i<=N; i++) if (!cut[i] && d[i]==M-N+2) printf("%d ",i); puts(""); return 0; }
曼哈顿距离最小生成树
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; int read() { int x=0,f=1; char ch=getchar(); while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();} while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();} return x*f; } #define MAXN 100010 int N; struct PointNode{int x,y,id;}P[MAXN]; bool cmpP(PointNode A,PointNode B) {return A.x!=B.x? A.x<B.x : A.y<B.y;} struct UnionFind { int Fa[MAXN]; void Init() {for (int i=1; i<=N; i++) Fa[i]=i;} int Find(int x) {if (Fa[x]==x) return x; else return Fa[x]=Find(Fa[x]);} bool Merge(int x,int y) {int f1=Find(x),f2=Find(y); if (f1==f2) return 0; Fa[f1]=f2; return 1;} }uf; int Dis(PointNode A,PointNode B) {return abs(A.x-B.x)+abs(A.y-B.y);} struct EdgeNode{int to,val,from;}edge[MAXN<<2]; int cnt; void AddEdge(int u,int v,int w) {cnt++; edge[cnt].from=u; edge[cnt].to=v; edge[cnt].val=w;} bool cmpE(EdgeNode A,EdgeNode B) {return A.val<B.val;} int lowbit(int x) {return x&-x;} struct BITNode{int minn,pos; void init() {minn=0x7fffffff; pos=-1;}}bit[MAXN]; void Update(int x,int val,int pos) { for (int i=x; i; i-=lowbit(i)) if (val<bit[i].minn) bit[i].minn=val,bit[i].pos=pos; } int Query(int x,int M) { int minn=0x7fffffff,pos=-1; for (int i=x; i<=M; i+=lowbit(i)) if (bit[i].minn<minn) minn=bit[i].minn,pos=bit[i].pos; return pos; } int num,Ans; void MST() { int a[MAXN],b[MAXN]; for (int k=0; k<=3; k++) { if (k==1 || k==3) for (int i=1; i<=N; i++) swap(P[i].x,P[i].y); else if (k==2) for (int i=1; i<=N; i++) P[i].x=-P[i].x; stable_sort(P+1,P+N+1,cmpP); for (int i=1; i<=N; i++) a[i]=b[i]=P[i].y-P[i].x; stable_sort(b+1,b+N+1); int M=unique(b+1,b+N+1)-b-1; for (int i=1; i<=M; i++) bit[i].init(); for (int i=N; i>=1; i--) { int pos=lower_bound(b+1,b+M+1,a[i])-b; int ans=Query(pos,M); if (ans!=-1) AddEdge(P[i].id,P[ans].id,Dis(P[i],P[ans])); Update(pos,P[i].x+P[i].y,i); } } stable_sort(edge+1,edge+cnt+1,cmpE); uf.Init(); for (int i=1; i<=cnt; i++) { int u=edge[i].from,v=edge[i].to; if (uf.Merge(u,v)) Ans+=edge[i].val,num++; if (num==N-1) break; } } int main() { N=read(); for (int i=1; i<=N; i++) P[i].x=read(),P[i].y=read(),P[i].id=i; MST(); printf("%d\n",Ans); return 0; }
数学相关
基础 快速幂&快速乘&逆元&ExGcd
long long quick_pow(long long x,long long y,long long p) { long long re=1; for (int i=y; i; i>>=1,x=x*x%p) if (i&1) re=re*x%p; return re; }
inline LL Mul(LL x,LL y) {return (x*y-(LL)(x/(long double)P*y+1e-3)*P+P)%P;}
#include<iostream> #include<cstdio> using namespace std; int n,mod,x,y; void exgcd(int a, int b) { if(b==0) { x = 1; y = 0; return; } exgcd(b, a%b); int t = x; x = y; y = t - a/b*y; } int main() { //n在模mod意义下的逆元 scanf("%d%d",&n,&mod); exgcd(n,mod); printf("%d\n",(x%mod+mod)%mod); return 0; } //================================ void prework() { memset(flag,0,sizeof(flag)); flag[1]=1; inv[1]=1;jc[1]=1;//inv为逆元,jc为阶乘 int cnt=0; for (int i=2; i<=maxn; i++) { jc[i]=jc[i-1]*i%p; if (!flag[i]) prime[++cnt]=i,inv[i]=quick_pow(i,p-2,p); for (int j=1; j<=cnt && i*prime[j]<=maxn; j++) { flag[i*prime[j]]=1; inv[i*prime[j]]=inv[i]*inv[prime[j]]%p; if (i%prime[j]==0) break; } } } //================================ inv[1]=1; for (int i=2; i<=maxn&&i<p; i++) inv[i]=(p-p/i)*inv[p%i]%p;
void exgcd(int a, int b) { if(b==0) { x = 1; y = 0; return; } exgcd(b, a%b); int t = x; x = y; y = t - a/b*y; }
拓展BSGS
#include<iostream> #include<cstring> #include<cstdio> #include<algorithm> #include<map> #include<cmath> using namespace std; long long gcd(long long a,long long b) { if (b==0) return a; else return gcd(b,a%b); } long long quick_pow(long long x,long long y,long long p) { long long re=1; x%=p; y%=p; for (long long i=y; i; i>>=1,x=x*x%p) if (i&1) re=re*x%p; return re; } long long bsgs(long long a,long long b,long long p){ if(a%=p,b%=p,b==1)return 0; long long t=1;long long f,g,delta=0,m=sqrt(p)+1,i; for(g=gcd(a,p);g!=1;g=gcd(a,p)){ if(b%g)return -1; b/=g,p/=g,t=t*(a/g)%p,delta++; if(b==t)return delta; } map<long long,long long>hash; for(i=0;i<m;i++,b=b*a%p)hash[b]=i; for(i=1,f=quick_pow(a,m,p);i<=m+1;i++) if(t=t*f%p,hash.count(t))return i*m-hash[t]+delta; return -1; } int main() { long long a,b,p; while (cin>>a>>b>>p) { //if (a==0 && b==0 && p==0) break; long long ans=bsgs(a,b,p); if (ans==-1) puts("No Solution"); else printf("%lld\n",ans); } return 0; }
Lucas定理
int quick_pow(long long a,int b,int p)//快速幂(算逆元) { int ans=1; for(int i=b;i;i>>=1,a=(a*a)%p) if(i&1)ans=(ans*a)%p; return ans; } void cs()//初始出阶乘 { jc[1][0]=jc[2][0]=jc[3][0]=jc[0][0]=1;//第一维无意义(因题目分成的几个模质数) for (int i=0; i<4; i++) for (int j=1; j<=pp[i]; j++) jc[i][j]=(jc[i][j-1]*j)%pp[i]; } int C(int n,int m,int p)//组合数 { if (n<m) return 0; return jc[p][n]*quick_pow(jc[p][m]*jc[p][n-m],pp[p]-2,pp[p])%pp[p]; } int lucas(int n,int m,int p)//lucas { if (m==0) return 1; return C(n%pp[p],m%pp[p],p)*lucas(n/pp[p],m/pp[p],p)%pp[p]; }
拓展lucas定理
#include<iostream> #include<cstdio> #include<cmath> #include<algorithm> #include<cstring> using namespace std; #define LL long long #define MAXN 100010 inline int read() { int x=0,f=1; char ch=getchar(); while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();} while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();} return x*f; } #define Pa pair<LL,LL> #define MP make_pair #define X first #define C second int N,M,P,w[MAXN]; inline LL Pow(LL x,LL y) {LL re=1; for (LL i=y; i; i>>=1,x=x*x) if (i&1) re=re*x; return re;} inline LL Pow(LL x,LL y,LL p) {LL re=1; for (LL i=y; i; i>>=1,x=x*x%p) if (i&1) re=re*x%p; return re;} inline void Exgcd(LL a,LL b,LL &x,LL &y) {if (!b) {x=1,y=0; return;} else Exgcd(b,a%b,y,x),y-=a/b*x;} inline LL Inv(LL x,LL p) {LL a,b; Exgcd(x,p,a,b); return (a%p+p)%p;} inline Pa Fac(LL x,LL p,LL c,LL pc) { if (x==1 || !x) return MP(1,0); int las=x%pc; LL re2=1,re1; for (int i=1; i<=las; i++) { if (!(i%p)) continue; re2=re2*i%pc; } if (x>=pc) { re1=re2; for (int i=las+1; i<pc; i++) { if (!(i%p)) continue; re1=re1*i%pc; } re1=Pow(re1,x/pc,pc); } else re1=1; int t=x/p; Pa re=Fac(x/p,p,c,pc); return MP(re1*re2%pc*re.X%pc,t+re.C); } inline LL Lucas(LL n,LL m,LL p,LL c,LL pc) { Pa n1=Fac(n,p,c,pc),m1=Fac(m,p,c,pc),nm1=Fac(n-m,p,c,pc); int rc=n1.C-m1.C-nm1.C; LL re=1; re=n1.X*Inv(m1.X,pc)%pc*Inv(nm1.X,pc)%pc; for (int i=1; i<=rc; i++) re=(re*p)%pc; return re; } int p[MAXN],cnt,ex[MAXN],pex[MAXN]; inline void Divide(int x) { int sx=x; for (int i=2; i*i<=sx; i++) { if (!(x%i)) { p[++cnt]=i; while (!(x%i)) ex[cnt]++,x/=i; pex[cnt]=Pow(i,ex[cnt]); } } if (x>1) p[++cnt]=x,pex[cnt]=x,ex[cnt]=1; } LL an[MAXN]; inline LL CRT(int n,int m) { LL re=0; for (int i=1; i<=cnt; i++) an[i]=Lucas(n,m,p[i],ex[i],pex[i]); for (int i=1; i<=cnt; i++) (re+=P/pex[i]*Inv((P/pex[i])%pex[i],pex[i])%P*an[i]%P)%=P; return re; } int main() { P=read(); Divide(P); N=read(),M=read(); LL tot=0; for (int i=1; i<=M; i++) w[i]=read(),tot+=w[i]; if (tot>N) return puts("Impossible"),0; LL ans=CRT(N,tot); for (int i=1; i<=M; i++) { ans=ans*CRT(tot,w[i])%P; tot-=w[i]; } printf("%lld\n",ans); return 0; }
线性筛欧拉函数&莫比乌斯函数&单个欧拉函数
long long prime[maxn],phi[maxn]; bool flag[maxn]={0}; int n; void get_phi() { memset(flag,0,sizeof(flag)); flag[1]=1; int cnt=0; for (int i=2; i<=maxn; i++) { if (!flag[i]) prime[cnt++]=i,phi[i]=i-1; for (int j=0; j<cnt && i*prime[j]<maxn; j++) { flag[i*prime[j]]=1; if (i%prime[j]==0) { phi[i*prime[j]]=phi[i]*prime[j]; break; } else phi[i*prime[j]]=phi[i]*(prime[j]-1); } } }
int prime[100010],tot,mu[100010];bool flag[100010]; void Prework(int x) { flag[1]=1; mu[1]=1; for (int i=2; i<=x; i++) { if (!flag[i]) prime[++tot]=i,mu[i]=-1; for (int j=1; j<=tot&&i*prime[j]<=x; j++) { flag[i*prime[j]]=1; if (!(i%prime[j])) {mu[i*prime[j]]=0; break;} else mu[i*prime[j]]=-mu[i]; } } }
int euler_phi(int n)//求单个欧拉函数 { int m=(int)sqrt(n+0.5); int i,ans=n; for(i=2;i<=m;i++) if(n%i==0) { ans=ans/i*(i-1); while(n%i==0)n/=i; } if(n>1)ans=ans/n*(n-1); return ans; }
杜教筛 $\phi$前缀和 $\mu$前缀和
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; #define LL long long #define N 5000000 #define P 233333 #define MAXN 250000 LL T,X; int prime[N+10],cnt,flag[N+10]; LL phi[N+10],mu[N+10]; inline void Euler(int n) { flag[1]=1,phi[1]=1,mu[1]=1; for (int i=2; i<=n; i++) { if (!flag[i]) prime[++cnt]=i,mu[i]=-1,phi[i]=i-1; for (int j=1; j<=cnt && i*prime[j]<=n; j++) { flag[i*prime[j]]=1; if (!(i%prime[j])) { mu[i*prime[j]]=0; phi[i*prime[j]]=phi[i]*prime[j]; break; } mu[i*prime[j]]=-mu[i]; phi[i*prime[j]]=phi[i]*(prime[j]-1); } } for (int i=1; i<=n; i++) mu[i]+=mu[i-1],phi[i]+=phi[i-1]; } #define INF -(1LL<<62) struct Node{ int next; LL i,x; }; struct Hash{ Node mp[MAXN]; int head[MAXN],tot; inline void Add(LL i,LL x) {int pos=i%P; tot++; mp[tot].i=i; mp[tot].x=x; mp[tot].next=head[pos]; head[pos]=tot;} inline LL Find(LL i) { int pos=i%P; for (int j=head[pos]; j; j=mp[j].next) if (mp[j].i==i) return mp[j].x; return INF; } }Phi,Mu; inline LL Sumphi(LL x) { if (x<=N) return phi[x]; else { LL re=Phi.Find(x); if (re!=INF) return re; } LL sum=0; for (LL i=2,j; i<=x; i=j+1) j=x/(x/i),sum+=Sumphi(x/i)*(j-i+1); Phi.Add(x,x*(x+1)/2-sum); return x*(x+1)/2-sum; } inline LL Summu(LL x) { if (x<=N) return mu[x]; else { LL re=Mu.Find(x); if (re!=INF) return re; } LL sum=0; for (LL i=2,j; i<=x; i=j+1) j=x/(x/i),sum+=Summu(x/i)*(j-i+1); Mu.Add(x,1LL-sum); return 1LL-sum; } int main() { Euler(N); scanf("%d",&T); while (T--) { scanf("%lld",&X); printf("%lld %lld\n",Sumphi(X),Summu(X)); } return 0; }
中国剩余定理
#include <iostream> #include<cstdio> using namespace std; int Extended_Euclid(int a,int b,int &x,int &y) //扩展欧几里得算法 { int d; if(b==0) { x=1;y=0; return a; } d=Extended_Euclid(b,a%b,y,x); y-=a/b*x; return d; } int Chinese_Remainder(int a[],int w[],int len) //中国剩余定理 a[]存放余数 w[]存放两两互质的数 { int i,d,x,y,m,n,ret; ret=0; n=1; for (i=0;i<len;i++) n*=w[i]; for (i=0;i<len;i++) { m=n/w[i]; d=Extended_Euclid(w[i],m,x,y); ret=(ret+y*m*a[i])%n; } return (n+ret%n)%n; } int main() { int n,i; int w[15],b[15],cs[15]; while (scanf("%d",&n),n) { for (i=0;i<n;i++) { scanf("%d%d%d",&cs[i],&w[i],&b[i]); } printf("%d\n",Chinese_Remainder(b,w,n)); } return 0; }
高斯消元&线性基
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; inline int read() { int x=0,f=1; char ch=getchar(); while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();} while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();} return x*f; } #define MAXN 1100 #define eps 1e-5 double a[MAXN][MAXN],x[MAXN]; int N,M,flag; //flag=1 唯一解 0无解 -1不唯一解 inline void Gauss() { flag=1; for (int i=1; i<=M; i++) { int mx=i; for (int j=i+1; j<=N; j++) if (abs(a[j][i])>abs(a[mx][i])) mx=j; swap(a[i],a[mx]); if (abs(a[i][i])<eps) {flag=-1; continue;} for (int j=i+1; j<=M+1; j++) a[i][j]/=a[i][i]; a[i][i]=1; for (int j=i+1; j<=N; j++) { for (int k=i+1; k<=M+1; k++) a[j][k]-=a[j][i]*a[i][k]; a[j][i]=0; } // puts(""); // for (int j=1; j<=N; j++,puts("")) // for (int k=1; k<=M+1; k++) // printf("%.1lf ",a[j][k]); // puts("================"); } for (int i=1,f=1; i<=N; i++,f=1) { for (int j=1; j<=M && f; j++) if (abs(a[i][j])>eps) f=0; if (abs(a[i][M+1])>eps && f) flag=0; } if (flag==0) return; for (int i=M; i>=1; i--) { x[i]=a[i][M+1]; for (int j=i+1; j<=M; j++) x[i]-=x[j]*a[i][j]; } } int main() { M=read(),N=read(); for (int i=1; i<=N; i++) for (int j=1; j<=M+1; j++) a[i][j]=read(); Gauss(); switch (flag) { case 1: for (int i=1; i<=M; i++) printf("%.2lf\n",x[i]); break; case 0: puts("No solutions"); break; case -1: puts("Many solutions"); break; } return 0; }
#include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<algorithm> using namespace std; #define LL long long inline LL read() { LL x=0,f=1; char ch=getchar(); while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();} while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();} return x*f; } int T,N,Q,M,flag,cas; LL a[100010],lb[100010]; inline void Gauss() { M=0; flag=0; int i; for (LL j=1LL<<62; j; j>>=1) { for (i=M+1; i<=N; i++) if (a[i]&j) break; if (i>N) continue; swap(a[++M],a[i]); for (i=1; i<=N; i++) if (i!=M && a[i]&j) a[i]^=a[M]; } if (M!=N) flag=1; for (int i=1; i<=M;i++) lb[i]=a[i]; } int main() { T=read(); while (T--) { printf("Case #%d:\n",++cas); N=read(); for (int i=1; i<=N; i++) a[i]=read(); Gauss(); LL Num=(1LL<<M); Q=read(); for (int i=1; i<=Q; i++) { LL k=read(),ans=0; if (flag) k--; if (k>=Num) {puts("-1"); continue;} if (!k) {puts("0"); continue;} for (int j=1; j<=M; j++) if (k&(1LL<<(M-j))) ans^=lb[j]; printf("%lld\n",ans); } } return 0; }
Pollar_Rho分解&Miller_Rabin判质数
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> #include<cstdlib> using namespace std; long long read() { long long x=0,f=1; char ch=getchar(); while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();} while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();} return x*f; } long long e,N,c,r,P,Q; long long Quick_Mul(long long x,long long y,long long p) { long long re=0; for (long long i=y; i; i>>=1,x=(x+x)%p) if (i&1) re=(re+x)%p; return re; } long long Quick_Pow(long long x,long long y,long long p) { long long re=1; for (long long i=y; i; i>>=1,x=Quick_Mul(x,x,p)) if (i&1) re=Quick_Mul(re,x,p); return re; } void Exgcd(long long a,long long b,long long &x,long long &y) { if (b==0) {x=1; y=0; return;} Exgcd(b,a%b,y,x); y-=(a/b)*x; } long long GetInv(long long n,long long p) { long long x,y; Exgcd(n,p,x,y); return (x%p+p)%p; } long long Gcd(long long a,long long b) { if (b==0) return a; return Gcd(b,a%b); } #define T 10007 long long Pollard_Rho(long long n) { long long x,y,cnt=1,k=2; x=rand()%(n-1)+1; y=x; while (1) { cnt++; x=(Quick_Mul(x,x,n)+T)%n; long long gcd=Gcd(abs(x-y),n); if (1<gcd && gcd<n) return gcd; if (x==y) return n; if (cnt==k) y=x,k<<=1; } } int main() { srand(T); e=read(),N=read(),c=read(); P=Pollard_Rho(N); Q=N/P; r=(P-1)*(Q-1); long long Inv=GetInv(e,r); printf("%lld %lld",Inv,Quick_Pow(c,Inv,N)); return 0; }
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<ctime> #include<cstdlib> using namespace std; long long read() { long long x=0,f=1; char ch=getchar(); while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();} while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();} return x*f; } long long X,maxz; long long gcd(long long a,long long b) { if (b==0) return a; return gcd(b,a%b); } //long long mul(long long a,long long b,long long p) //{ // if (b==0) return 0; if (b==1) return a%p; // long long re; // re=mul(a,b>>1,p); // if ((b&1)==1) return (re+re+a)%p; // else return (re+re)%p; //} long long mul(long long a,long long b,long long p) { long long tmp=(a*b-(long long)((long double)a/p*b+1e-8)*p); return tmp<0?tmp+p:tmp; } long long quick_pow(long long a,long long b,long long p) { long long ans=1; a%=p; for (long long i=b; i; i>>=1,a=mul(a,a,p)) if (i&1) ans=mul(ans,a,p); return ans; } bool check(long long a,long long n,long long r,long long s) { long long ans=quick_pow(a,r,n),p=ans; for(int i=1; i<=s; i++) { ans=mul(ans,ans,n); if(ans==1&&p!=1&&p!=n-1)return 1; p=ans; } if(ans!=1)return 1;else return 0; } bool Robin_Miller(long long x) { if(x<=1) return 0; if(x==2) return 1; if(x%2==0) return 0; long long r=x-1,s=0; while(r%2==0) r/=2,s++; for(int i=0; i<20; i++) if(check(rand()%(x-1)+1,x,r,s)) return 0; return 1; } long long Rho(long long x,long long t) { long long k=2,a=rand()%x,b=a,p=1; for(long long i=1; p==1; i++) { a=(mul(a,a,x)+t)%x; p=b>a?b-a:a-b; p=gcd(x,p); if(i==k) b=a,k+=k; } return p; } void work(long long x) { if(x==1) return; if(Robin_Miller(x)){maxz=max(x,maxz);return;} long long t=x; while(t==x) t=Rho(x,rand()%(x-1)+1); work(t); work(x/t); } int main() { int n;n=read(); while (n--) { X=read(); maxz=0; work(X); if (maxz==X) puts("Prime"); else printf("%lld\n",maxz); } return 0; }
FFT&NTT
#include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<algorithm> using namespace std; inline int read() { int x=0,f=1; char ch=getchar(); while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();} while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();} return x*f; } #define MAXN 400010 #define Pai acos(-1.0) struct Complex{ double r,i; Complex(double R=0.0,double I=0.0) {r=R,i=I;} Complex operator - (const Complex & A) const {return Complex(r-A.r,i-A.i);} Complex operator + (const Complex & A) const {return Complex(r+A.r,i+A.i);} Complex operator * (const Complex & A) const {return Complex(r*A.r-i*A.i,r*A.i+A.r*i);} }; Complex A[MAXN],B[MAXN],C[MAXN]; int N,M,a[MAXN],b[MAXN],ans[MAXN],len; inline void Prework() { len=1; while (len<(N+1+M+1)) len<<=1; for (int i=0; i<=N; i++) A[i]=Complex(a[i+1],0); for (int i=0; i<=M; i++) B[i]=Complex(b[i+1],0); for (int i=N+1; i<len; i++) A[i]=Complex(0,0); for (int i=M+1; i<len; i++) B[i]=Complex(0,0); // for (int i=0; i<len; i++) printf("%d ",(int)(A[i].r+0.5)); puts(""); // for (int i=0; i<len; i++) printf("%d ",(int)(B[i].r+0.5)); puts(""); } inline void Rader(Complex *x) { for (int i=1,j=len>>1,k; i<len-1; i++) { if (i<j) swap(x[i],x[j]); k=len>>1; while (j>=k) j-=k,k>>=1; if (j<k) j+=k; } } inline void DFT(Complex *x,int opt) { Rader(x); for (int h=2; h<=len; h<<=1) { Complex Wn( cos(opt*2*Pai/h),sin(opt*2*Pai/h) ); for (int i=0; i<len; i+=h) { Complex W(1,0); for (int j=i; j<i+h/2; j++) { Complex u=x[j],t=W*x[j+h/2]; x[j]=u+t; x[j+h/2]=u-t; W=W*Wn; } } } if (opt==-1) for (int i=0; i<len; i++) x[i].r/=len; } inline void FFT(Complex *A,Complex *B) { DFT(A,1); DFT(B,1); for (int i=0; i<len; i++) C[i]=A[i]*B[i]; DFT(C,-1); for (int i=0; i<len; i++) ans[i]=(int)(C[i].r+0.5); } int main() { N=read(),M=read(); for (int i=1; i<=N+1; i++) a[i]=read(); for (int i=1; i<=M+1; i++) b[i]=read(); Prework(); FFT(A,B); for (int i=0; i<=N+M; i++) printf("%d ",ans[i]); puts(""); return 0; }
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> using namespace std; inline int read() { int x=0,f=1; char ch=getchar(); while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();} while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();} return x*f; } #define MAXN 300010 #define LL long long #define P ((479<<21)+1) #define G 3 int N,M,a[MAXN],b[MAXN],len; LL wn[MAXN],A[MAXN],B[MAXN],C[MAXN]; inline LL Pow(LL x,LL y) { LL re=1; for (int i=y; i; i>>=1,x=x*x%P) if (i&1) re=re*x%P; return re; } inline LL Inv(LL x) {return Pow(x,P-2);} inline void Prework() { len=1; while (len<(N+1+M+1)) len<<=1; for (int i=0; i<=N; i++) A[i]=a[i+1]; for (int i=0; i<=M; i++) B[i]=b[i+1]; for (int i=N+1; i<len; i++) A[i]=0; for (int i=M+1; i<len; i++) B[i]=0; for (int i=0; i<21; i++) wn[i]=Pow(G,(P-1)/(1<<i)); } inline void Rader(LL *x) { for (int i=1,j=len>>1,k; i<len-1; i++) { if (i<j) swap(x[i],x[j]); k=len>>1; while (j>=k) j-=k,k>>=1; if (j<k) j+=k; } } inline void DFT(LL *x,int opt) { Rader(x); for (int h=2,id=0; h<=len; h<<=1) { LL Wn=wn[++id]; for (int i=0; i<len; i+=h) { LL W=1; for (int j=i; j<i+h/2; j++) { LL u=x[j]%P,t=W*x[j+h/2]%P; x[j]=(u+t)%P; x[j+h/2]=(u-t+P)%P; W=W*Wn%P; } } } if (opt==-1) { for (int i=1; i<len/2; i++) swap(x[i],x[len-i]); for (int i=0; i<len; i++) x[i]=x[i]*Inv(len)%P; } } inline void NTT(LL *A,LL *B) { DFT(A,1); DFT(B,1); for (int i=0; i<len; i++) C[i]=A[i]*B[i]%P; DFT(C,-1); } int main() { N=read(),M=read(); for (int i=1; i<=N+1; i++) a[i]=read(); for (int i=1; i<=M+1; i++) b[i]=read(); Prework(); NTT(A,B); for (int i=0; i<=N+M; i++) printf("%d ",C[i]); puts(""); return 0; }
字符串相关
Hash
#include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<cstring> using namespace std; int N,L,SS,ans=0; unsigned long long bin[210],hash[30010][210],HASH[30010]; char S[30010][210]; #define BASE 131 void Hash(char *s,unsigned long long t) { for (int i=1; i<=L; i++) hash[t][i]=hash[t][i-1]*BASE+s[i]; } unsigned long long GetHash(unsigned long long t,int l) { return hash[t][L]-hash[t][l]*bin[L-l]+hash[t][l-1]*bin[L-l+1]; } int main() { scanf("%d%d%d",&N,&L,&SS); bin[0]=1; for (int i=1; i<=L; i++) bin[i]=bin[i-1]*BASE; for (int i=1; i<=N; i++) scanf("%s",S[i]+1),Hash(S[i],i); for (int i=1; i<=L; i++) { for (int j=1; j<=N; j++) HASH[j]=GetHash(j,i); sort(HASH+1,HASH+N+1); HASH[N+1]=0; for (int pre=1,cnt,j=1; j<=N+1; j++) if (HASH[j]!=HASH[pre]) cnt=j-pre,ans+=cnt*(cnt-1)/2,pre=j; } printf("%d\n",ans); return 0; }
KMP
inline void GetNext() { Next[1]=0; for (int j=0,i=2; i<=l[1]; i++) { while (j && s[1][j+1]!=s[1][i]) j=Next[j]; if (s[1][j+1]==s[1][i]) j++; Next[i]=j; } } inline int KMP(int x,int st) { int len=0; for (int i=1,j=st-1; i<=l[x]-1; i++) { while (j>=st && s[x][i]!=s[1][j+1]) j=Next[j]; if (j<st) j=st-1; if (s[1][j+1]==s[x][i]) j++; len=max(len,j-st+1); if (j==l[1]-1) break; } return len; }
AC自动机
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include<queue> using namespace std; #define MAXN 1000100 int K,N,loc[MAXN],visit[MAXN]; struct EdgeNode{int next,to;}edge[MAXN<<1]; int head[MAXN],cnt=1; inline void AddEdge(int u,int v) {cnt++; edge[cnt].next=head[u]; head[u]=cnt; edge[cnt].to=v;} inline void InsertEdge(int u,int v) {AddEdge(u,v); AddEdge(v,u);} char S[MAXN]; namespace FailTree { int son[MAXN][27],end[MAXN],sz=1,fail[MAXN]; #define id(str) str-'a'+1 inline int Insert(int x,char str[]) { int len=strlen(str+1),now=1; for (int i=1; i<=len; i++) if (son[now][id(str[i])]) now=son[now][id(str[i])]; else son[now][id(str[i])]=++sz,now=sz; end[now]=1; loc[x]=now; } queue<int>q; inline void Getfail() { q.push(1); while (!q.empty()) { int now=q.front(); q.pop(); for (int i=1; i<=26; i++) if (son[now][i]) { int fa=fail[now]; while (fa && !son[fa][i]) fa=fail[fa]; fail[son[now][i]]=fa? son[fa][i]:1; q.push(son[now][i]); } } for (int i=1; i<=sz; i++) InsertEdge(fail[i],i); } } using namespace FailTree; namespace Divide { int pl[MAXN],pr[MAXN],dfn,tree[MAXN<<1]; inline void DFS(int now,int last) { pl[now]=++dfn; for (int i=head[now]; i; i=edge[i].next) if (edge[i].to!=last) DFS(edge[i].to,now); pr[now]=++dfn; } inline int lowbit(int x) {return x&-x;} inline void Modify(int pos,int D) {for (int i=pos; i<=dfn; i+=lowbit(i)) tree[i]+=D;} inline int Query(int pos) {int re=0; for (int i=pos; i; i-=lowbit(i)) re+=tree[i]; return re;} inline int Calc(char str[]) { int len=strlen(str+1),ans=0,now=1; for (int i=1; i<=len; i++) { while (now && !son[now][id(str[i])]) now=fail[now]; now=now? son[now][id(str[i])]:1; ans+=Query(pl[now]); } return ans; } inline void Change(int x,int D) { if (visit[x] && D>0) return; if (!visit[x] && D<0) return; visit[x]^=1; Modify(pl[loc[x]],D); Modify(pr[loc[x]],-D); } } using namespace Divide; int main() { scanf("%d%d",&K,&N); for (int i=1; i<=N; i++) scanf("%s",S+1),Insert(i,S); Getfail(); DFS(1,0); for (int i=1; i<=N; i++) Modify(pl[loc[i]],1),Modify(pr[loc[i]],-1),visit[i]=1; while (K--) { char opt=getchar(); int x; while (opt!='+' && opt!='-' && opt!='?') opt=getchar(); switch (opt) { case '+' : scanf("%d",&x); Change(x,1); break; case '-' : scanf("%d",&x); Change(x,-1); break; case '?' : scanf("%s",S+1); printf("%d\n",Calc(S)); break; } } return 0; }
Manacher
#include<iostream> #include<cstring> #include<cstdio> #include<algorithm> #include<cmath> using namespace std; #define maxn 50010<<1 int n,len,mx,id,p[maxn],cnt; char S[maxn>>1],s[maxn]; struct TreeNode { int a[maxn]; void init() {memset(a,127,sizeof(a));} int lowbit(int x) {return x&(-x);} int Query(int loc) { if (!loc) return 0; int x=0x7fffffff; for (int i=loc; i<=n; i+=lowbit(i)) x=min(x,a[i]); return x; } void Change(int loc,int D) { for (int i=loc; i; i-=lowbit(i)) a[i]=min(a[i],D); } }Tree; void PreWork() { cnt=0; mx=0; id=0; Tree.init(); memset(p,0,sizeof(p)); n=strlen(S+1); len=n<<1|1; s[0]='$'; s[1]='#'; s[len+1]='%'; for (int i=1; i<=n; i++) s[i<<1]=S[i],s[i<<1|1]='#'; } struct HWCNode { int l,r; bool operator < (const HWCNode & A) const {return r<A.r;} }Line[maxn]; void Manacher() { PreWork(); for (int i=1; i<=len; i++) { if (mx>i) p[i]=min(p[id*2-i],mx-i); else p[i]=1; while (s[i-p[i]]==s[p[i]+i]) p[i]++; int x=(i-p[i])/2+1,y=(i+p[i])/2-1; if (x<=y) Line[++cnt].l=x,Line[cnt].r=y; if (p[i]+i>mx) mx=p[i]+i,id=i; } } int DP() { int ans=0x7fffffff; sort(Line+1,Line+cnt+1); for (int i=1; i<=cnt; i++) { int D=Tree.Query(Line[i].l-1)+1; Tree.Change(Line[i].r,D); if (Line[i].r==n) ans=min(ans,D); } return ans-1; } int main() { while (scanf("%s",S+1)!=EOF) Manacher(),printf("%d\n",DP()); return 0; }
后缀数组
#include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<algorithm> using namespace std; #define LL long long inline int read() { int x=0,f=1; char ch=getchar(); while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();} while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();} return x*f; } #define MAXN 100010 int N,K,a[MAXN]; int R[MAXN],SA[MAXN],height[MAXN],rank[MAXN],t1[MAXN],t2[MAXN],st[MAXN]; inline void Sort(int *x,int *y,int *sa,int L,int M) { for (int i=0; i<=M; i++) st[i]=0; for (int i=0; i<L; i++) st[x[y[i]]]++; for (int i=1; i<=M; i++) st[i]+=st[i-1]; for (int i=L-1; i>=0; i--) sa[--st[x[y[i]]]]=y[i]; } inline void DA(int *r,int *sa,int L,int M) { int *x=t1,*y=t2,*t,i,j,p; for (int i=0; i<L; i++) x[i]=r[i],y[i]=i; Sort(x,y,sa,L,M); for (j=1,p=1; j<L && p<L; j<<=1,M=p-1) { for (p=0,i=L-j; i<L; i++) y[p++]=i; for (i=0; i<L; i++) if (sa[i]>=j) y[p++]=SA[i]-j; Sort(x,y,sa,L,M); for (t=x,x=y,y=t,i=1,x[sa[0]]=0,p=1; i<L; i++) x[sa[i]]=y[sa[i-1]]==y[sa[i]] && y[sa[i-1]+j]==y[sa[i]+j]? p-1:p++; } } inline void Height(int *r,int *sa,int *rank,int *h,int L) { h[1]=0; for (int i=1; i<=L; i++) rank[sa[i]]=i; for (int i=1,k=0,j; i<=L; h[rank[i++]]=k) for (k? --k:k=0,j=sa[rank[i]-1]; r[j+k]==r[i+k]; k++); } int log_2[MAXN],dp[MAXN][21]; inline void St(int L) { log_2[0]=-1; for (int i=1; i<=L; i++) if (i&(i-1)) log_2[i]=log_2[i-1]; else log_2[i]=log_2[i-1]+1; for (int i=0; i<=L; i++) dp[i][0]=height[i+1]; for (int j=1; (1<<j)<=L; j++) for (int i=0; i+(1<<j)-1<=L; i++) dp[i][j]=min(dp[i][j-1],dp[i+(1<<(j-1))][j-1]); } inline int RMQ(int l,int r) {int k=log_2[r-l]; return min(dp[l][k],dp[r-(1<<k)][k]);} inline int LCP(int l,int r) {l=rank[l],r=rank[r]; if (l>r) swap(l,r); return RMQ(l,r);} int ls[MAXN]; int main() { N=read(),K=read(); for (int i=1; i<=N; i++) a[i]=read(); for (int i=1; i<=N-1; i++) ls[i]=R[i]=a[i+1]-a[i]; for (int i=1; i<=N-1; i++) R[N+i]=R[N-1-i+1]; sort(ls+1,ls+N-1+1); int mx=unique(ls+1,ls+N-1+1)-ls-1; // for (int i=1; i<=2*N-1; i++) printf("%d ",R[i]); puts(""); for (int i=1; i<=2*N-1; i++) R[i]=lower_bound(ls+1,ls+mx+1,R[i])-ls; R[N]=mx+1; // for (int i=1; i<=2*N-1; i++) printf("%d ",R[i]); puts(""); DA(R,SA,2*N-1+1,mx+1); Height(R,SA,rank,height,2*N-1); St(2*N-1); LL ans=0; for (int len=1; len*2+K<=N-1; len++) { int pre=0,suf=0; for (int i=1; i+len+K<=N-1; i+=len) { suf=min(len,LCP(i,i+len+K)); if (i>1) pre=min(len-1,LCP(2*N-1-i+1+1,2*N-1-(i+len+K)+1+1)); else pre=0; // printf("%d %d %d %d->",i,i+len+K,2*N-1-i+1,2*N-1-(i+len+K)+1); if (suf+pre>=len) ans+=(LL)(suf+pre-len+1); // printf("%d %d %d %d %I64d\n",i,len,pre,suf,ans); } } printf("%lld\n",ans); return 0; }
后缀自动机
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; #define MAXN 1000010 char S[MAXN<<1]; int N,Q; namespace SAM { int son[MAXN<<1][27],len[MAXN<<1],par[MAXN<<1],size[MAXN<<1]; int last,sz=1,root=1; inline void Init() {last=root;} inline void Extend(int c) { int cur=++sz,p=last; len[cur]=len[p]+1; size[cur]=1; while (p && !son[p][c]) son[p][c]=cur,p=par[p]; if (!p) par[cur]=root; else { int q=son[p][c]; if (len[p]+1==len[q]) par[cur]=q; else { int nq=++sz; memcpy(son[nq],son[q],sizeof(son[nq])); len[nq]=len[p]+1; par[nq]=par[q]; while (p && son[p][c]==q) son[p][c]=nq,p=par[p]; par[cur]=par[q]=nq; } } last=cur; } inline void Build() {Init(); for (int i=1; i<=N; i++) Extend(S[i]-'a'+1);} int st[MAXN],id[MAXN<<1]; inline void Pre() { for (int i=1; i<=sz; i++) st[len[i]]++; for (int i=1; i<=N; i++) st[i]+=st[i-1]; for (int i=1; i<=sz; i++) id[st[len[i]]--]=i; for (int i=sz; i>=1; i--) size[par[id[i]]]+=size[id[i]]; } int flag[MAXN<<1]; inline void Query() { int now=root,L=0,ans=0; for (int i=1; i<=N+N; i++) { int c=S[i]-'a'+1; if (son[now][c]) L++,now=son[now][c]; else { while (now && !son[now][c]) now=par[now]; if (!now) now=root,L=0; else L=len[now]+1,now=son[now][c]; } if (i>N && L>=N) { int tmp=now; while (tmp && !(N>=len[par[tmp]]+1 && N<=len[tmp])) tmp=par[tmp]; if (!tmp) tmp=root; if (flag[tmp]!=Q+1) ans+=size[tmp],flag[tmp]=Q+1; } } printf("%d\n",ans); } }using namespace SAM; int main() { scanf("%s",S+1); N=strlen(S+1); SAM::Build(); SAM::Pre(); scanf("%d",&Q); while (Q--) { scanf("%s",S+1); N=strlen(S+1); for (int i=1; i<=N; i++) S[N+i]=S[i]; SAM::Query(); } return 0; }
计算几何
平面计算几何合集
#include<cstdio> #include<iostream> #include<algorithm> #include<cstring> #include<cmath> #include<vector> #include<queue> #include<map> #include<set> #include<stack> #include<cstdlib> #include<string> #include<bitset> #include<iomanip> #define INF 1000000000 #define fi first #define se second #define N 100005 #define debug(x) cerr<<#x<<"="<<x<<endl #define MP(x,y) make_pair(x,y) using namespace std; typedef long long LL; typedef pair<int,int> pii; typedef long double Double; struct Vector { double x,y; Vector(double X=0,double Y=0) {x=X,y=Y;} }; struct Line { Point P; Vector v; double ang;//ang为极角 Line() {} Line(Point P,Vector v):P(P),v(v) {ang=atan2(v.y,v.x);} bool operator<(const Line &L) const {return ang<L.ang;} }; //向量/点、直线的存储 typedef Vector Point; typedef vector<Point> Polygon; const double eps=1e-12; const double pi=acos(-1.0); //初始化 Vector operator + (Vector A,Vector B) {return ((Vector){A.x+B.x,A.y+B.y});} Vector operator - (Vector A,Vector B) {return ((Vector){A.x-B.x,A.y-B.y});} Vector operator * (Vector A,double p) {return ((Vector){A.x*p,A.y*p});} Vector operator / (Vector A,double p) {return ((Vector){A.x/p,A.y/p});} bool operator < (const Vector& a,const Vector& b) {return a.x<b.x||(a.x==b.x&&a.y<b.y);} bool operator == (const Vector& a,const Vector& b) {return dcmp(a.x-b.x)==0&&dcmp(a.y-b.y)==0;} //重载一下相关运算符 int dcmp(double x) {if(fabs(x)<eps) return 0; else return x<0? -1:1;} //精度控制 double Dot(Vector A,Vector B) {return A.x*B.x+A.y*B.y;} //向量点积 double Len(Vector A) {return sqrt(Dot(A,A));} //求向量模长 double Angle(Vector A,Vector B) {return acos(Dot(A,B)/Len(A)/Len(B));} //求向量间夹角 double Cross(Vector A,Vector B) {return A.x*B.y-A.y*B.x;} //向量叉积 double Area2(Point A,Point B,Point C) {return Cross(B-A,C-A);} //求平行四边形面积 Vector Rotate(Vector A,double rad) {return ((Vector){A.x*cos(rad)-A.y*sin(rad), A.x*sin(rad)+A.y*cos(rad)});} //向量旋转(考虑成:对一个向量拆分成XY坐标系上的两个向量并分别旋转来计算) Vector Normal(Vector A) {double L=Len(A); return Vector(-A.y/L,A.x/L);} //计算单位法向量,其中A应该是非零向量 bool OnLeft(Line L,Point p) {return dcmp(Cross(L.v,p-L.P))>=0;} //利用叉积去判断点在直线的左/右 Point GLI(Point P,Vector v,Point Q,Vector w) {Vector u=P-Q; double t=Cross(w,u)/Cross(v,w); return P+v*t;} Point GLI(Line a,Line b) {Vector u=a.P-b.P; double t=Cross(b.v,u)/Cross(a.v,b.v);return a.P+a.v*t;} //直线与直线的交点,考虑面积法 double DisTL(Point P,Point A,Point B) {Vector v1=B-A,v2=P-A; return fabs(Cross(v1,v2)/Len(v1));} //点到直线的距离 double DisTS(Point P,Point A,Point B) { if(A==B) return Len(P-A); Vector v1=B-A, v2=P-A, v3=P-B; if(dcmp(Dot(v1,v2))<0) return Len(v2); else if(dcmp(Dot(v1,v3))>0) return Len(v3); else return fabs(Cross(v1,v2))/Len(v1); } //点到线段的距离(需要进行判断,如果点到直线的垂线段垂足在线段上,则可以直接返回与直线交点,否则为靠近的点得距离) bool OnSegment(Point P,Point A,Point B) {return dcmp(DisTL(P,A,B))==0&&dcmp(Dot(P-A,P-B))<0&&!(P==A)&&!(P==B);} //判断是否在线段上 double PolygonArea(Point* p,int n) { double area=0; for(int i=1;i<n-1;i++) area+=Cross(p[i]-p[0],p[i+1]-p[0]); return area/2; } double PolygonArea(Polygon p) { double area=0; int n=p.size(); for(int i=1;i<n-1;i++) area+=Cross(p[i]-p[0],p[i+1]-p[0]); return area/2; } //求多边形面积(应用三角剖分)经证明可以随意选基准点 int PInP(Point p,Point* poly,int n) { int wn=0,k,d1,d2; for(int i=0;i<n;i++) { if(dcmp(DisTS(p,poly[i],poly[(i+1)%n])==0)) return -1; k=dcmp(Cross(poly[(i+1)%n]-poly[i],p-poly[i])); d1=dcmp(poly[i].y-p.y); d2=dcmp(poly[(i+1)%n].y-p.y); if(k>0&&d1<=0&&d2>0) wn++; if(k<0&&d2<=0&&d1>0) wn--; } if(wn) return 1; else return 0; } //判断点是否在多面型内(射线法) int ConvexHull(Point* p,int n,Point* ch) //have no three point on one line { sort(p,p+n); int k,i,m=0; for(i=0;i<n;i++) { while(m>1&&dcmp(Cross(ch[m-1]-ch[m-2],p[i]-ch[m-2]))<=0) m--; ch[m++]=p[i]; } k=m; for(i=n-2;i>=0;i--) { while(m>k&&dcmp(Cross(ch[m-1]-ch[m-2],p[i]-ch[m-2]))<=0) m--; ch[m++]=p[i]; } if(n>1) m--; return m; } //Graham扫描法求凸包 double Rotating_calipers(Point* ch,int n) { if(n==1) return 0; if(n==2) return Len(ch[0]-ch[1]); int now=1,i; double ans=0; ch[n]=ch[0]; for(i=0;i<n;i++) { while(dcmp(DisTL(ch[now],ch[i],ch[i+1])-DisTL(ch[now+1],ch[i],ch[i+1]))<=0) now=(now+1)%n; ans=max(ans,Len(ch[now]-ch[i])); ans=max(ans,Len(ch[now]-ch[i+1])); } return ans; } //旋转卡壳求平面最远点对距离 double Rotating_calipers2(Point* p,Point* q,int n,int m) { int x=0,y=0,i; double ans=1e10,t; for(i=0;i<n;i++) x=(p[i].y<p[x].y)?i:x; for(i=0;i<m;i++) y=(q[i].y<q[y].y)?i:y; p[n]=p[0]; q[m]=q[0]; for(i=0;i<n;i++) { while((t=dcmp(Cross(p[x]-p[x+1],q[y+1]-q[y])))<0) y=(y+1)%m; if(t==0) { ans=min(ans,DisTS(p[x],q[y+1],q[y])); ans=min(ans,DisTS(p[x+1],q[y+1],q[y])); ans=min(ans,DisTS(q[y],p[x],p[x+1])); ans=min(ans,DisTS(q[y+1],p[x],p[x+1])); } else ans=min(ans,DisTS(q[y],p[x],p[x+1])); x=(x+1)%n; } return ans; } //旋转卡壳计算最小凸包之间的距离 (必须做两次这个过程) Polygon CutPolygon(Polygon poly,Point A,Point B) //get the left of A->B { Polygon newpoly; Point C,D,ip; int n=poly.size(),i; for(i=0;i<n;i++) { C=poly[i]; D=poly[(i+1)%n]; if(dcmp(Cross(B-A,C-A))>=0) newpoly.push_back(C); if(dcmp(Cross(B-A,D-C))!=0) { ip=GLI(A,B-A,C,D-C); if(OnSegment(ip,C,D)) newpoly.push_back(ip); } } return newpoly; } //直线切凸包(半平面交) void InitPolygon(Polygon &poly,double inf) { poly.clear(); poly.push_back((Point){-inf,-inf}); poly.push_back((Point){inf,-inf}); poly.push_back((Point){inf,inf}); poly.push_back((Point){-inf,inf}); } int Halfplane_Intersection(Line* L,int n,Point* poly) { sort(L,L+n); int first,last,i; Point *p=new Point[n]; Line *q=new Line[n]; q[first=last=0]=L[0]; for(i=1;i<n;i++) { while(first<last&&!OnLeft(L[i],p[last-1])) last--; while(first<last&&!OnLeft(L[i],p[first])) first++; q[++last]=L[i]; if(dcmp(Cross(q[last].v,q[last-1].v)/Len(q[last].v))==0) { last--; if(OnLeft(q[last],L[i].P)) q[last]=L[i]; } if(first<last) p[last-1]=GLI(q[last-1],q[last]); } while(first<last&&!OnLeft(q[first],p[last-1])) last--; if(last-first<=1) return 0; p[last]=GLI(q[last],q[first]); int m=0; for(i=first;i<=last;i++) poly[m++]=p[i]; return m; } //半平面交(-InitPolygon先初始化一个极大的框) Point Center_of_gravity(Point A,Point B,Point C) { Point P=(A+B)/2,Q=(A+C)/2; Vector v=Rotate(B-A,pi/2),w=Rotate(C-A,pi/2); if(dcmp(Len(Cross(v,w)))==0)//这是三点一线的情况 { if(dcmp(Len(A-B)+Len(B-C)-Len(A-C))==0) return (A+C)/2; if(dcmp(Len(A-C)+Len(B-C)-Len(A-B))==0) return (A+B)/2; if(dcmp(Len(A-B)+Len(A-C)-Len(B-C))==0) return (B+C)/2; } return GLI(P,v,Q,w); } //求三角形外心(包含特判三点一线的情况) double Min_Cover_Circle(Point *p,int n,Point &c) { random_shuffle(p,p+n); c=p[0]; double r=0; int i,j,k; for(i=1;i<n;i++) if(dcmp(Len(c-p[i])-r)>0) { c=p[i],r=0; for(j=0;j<i;j++) if(dcmp(Len(c-p[j])-r)>0) { c=(p[i]+p[j])/2; r=Len(c-p[i]); for(k=0;k<j;k++) if(dcmp(Len(c-p[k])-r)>0) { c=Center_of_gravity(p[i],p[j],p[k]); r=Len(c-p[i]); } } } return r; } //最小圆覆盖(随机增量法) c为圆心,返回值为r int main() { return 0; }
辛普森积分
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; #define MAXN 1010 double alpha; int N,num; #define INF 1e12 #define eps 1e-5 struct Point { double x,y; Point (double X=0,double Y=0) {x=X; y=Y;} }; struct Circle { double r; Point c; Circle(Point C=(Point){0,0},double R=0) {c=C; r=R;} }C[MAXN]; struct Line { Point s,t; double k,b; Line(Point S=(Point){0,0},Point T=(Point){0,0}) { s=S,t=T; if (s.x>t.x) swap(s,t); k=(s.y-t.y)/(s.x-t.x); b=s.y-k*s.x; } double f(double x) {return k*x+b;} }l[MAXN]; int dcmp(double x) {if (fabs(x)<eps) return 0; return x<0? -1:1;} double F(double x) { double re=0; for (int i=1; i<=N; i++) //枚举圆是否与扫描线有交 { double d=fabs(x-C[i].c.x); if (dcmp(d-C[i].r)>0) continue; double len=2*sqrt(C[i].r*C[i].r-d*d); re=max(re,len); } for (int i=1; i<=num; i++) //枚举公切线 if (x>=l[i].s.x && x<=l[i].t.x) re=max(re,2*l[i].f(x)); return re; } //利用扫描线去判断 double Calc(double l,double r) {double mid=(l+r)/2; return (F(l)+F(r)+F(mid)*4)*(r-l)/6;} double Simpson(double l,double r,double now) { double mid=(l+r)/2; double x=Calc(l,mid),y=Calc(mid,r); if (!dcmp(now-x-y)) return now; else return Simpson(l,mid,x)+Simpson(mid,r,y); } void Solve() { double L=INF,R=-INF; for (int i=1; i<=N+1; i++) L=min(L,C[i].c.x-C[i].r),R=max(R,C[i].c.x+C[i].r); // printf("%lf\n%lf\n",L,R); for (int i=1; i<=N; i++) { double d=C[i+1].c.x-C[i].c.x; if (dcmp(d-fabs(C[i].r-C[i+1].r))<0) continue; //特判小圆被大圆覆盖的情况 double sina=(C[i].r-C[i+1].r)/d,cosa=sqrt(1-sina*sina); l[++num]=(Line){(Point){C[i].c.x+C[i].r*sina,C[i].r*cosa},(Point){C[i+1].c.x+C[i+1].r*sina,C[i+1].r*cosa}}; } printf("%.2lf\n",Simpson(L,R,Calc(L,R))); } int main() { scanf("%d%lf",&N,&alpha); double h,r; for (int i=1; i<=N+1; i++) scanf("%lf",&h), C[i]=(Circle){((Point){(h/tan(alpha))+C[i-1].c.x,0}),0}; for (int i=1; i<=N; i++) scanf("%lf",&r),C[i].r=r; // for (int i=1; i<=N+1; i++) // printf("%d %.2lf %.2lf\n",i,C[i].c.x,C[i].r); Solve(); return 0; }
花式套路
点分治
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<map> using namespace std; #define LL long long inline int read() { int x=0,f=1; char ch=getchar(); while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();} while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();} return x*f; } #define MAXN 100010 int N,M; map<LL,LL>hash; LL ans; namespace Math { LL power[MAXN],Inv[MAXN]; inline LL Gcd(LL a,LL b) {if (!b) return a; else return Gcd(b,a%b);} inline void ExGcd(LL a,LL b,LL &x,LL &y) {if (!b) {x=1,y=0; return;} ExGcd(b,a%b,y,x); y-=(a/b)*x;} inline LL inv(LL X) {LL x,y; ExGcd(X,M,x,y); return (x%M+M)%M;} inline LL Pow(LL x,LL y) {LL re=1; for (LL i=y; i; i>>=1,x=x*x%M) if (i&1) re=re*x%M; return re;} } using namespace Math; namespace TreeDivide { struct EdgeNode{int next,to,val;}edge[MAXN<<1]; int head[MAXN],cnt=1; inline void AddEdge(int u,int v,int w) {cnt++; edge[cnt].to=v; edge[cnt].next=head[u]; head[u]=cnt; edge[cnt].val=w;} inline void InsertEdge(int u,int v,int w) {AddEdge(u,v,w); AddEdge(v,u,w);} int size[MAXN],f[MAXN],visit[MAXN],root,deep[MAXN],Sz; LL Dig[MAXN]; inline void Getroot(int x,int last) { size[x]=1,f[x]=0; for (int i=head[x]; i; i=edge[i].next) if (!visit[edge[i].to] && edge[i].to!=last) { Getroot(edge[i].to,x); size[x]+=size[edge[i].to]; f[x]=max(f[x],size[edge[i].to]); } f[x]=max(f[x],Sz-f[x]); if (f[x]<f[root]) root=x; } inline void DFS(int now,int last) { LL D=(((M-Dig[now])+M)%M*Inv[deep[now]])%M; hash[D]++; for (int i=head[now]; i; i=edge[i].next) if (edge[i].to!=last && !visit[edge[i].to]) deep[edge[i].to]=deep[now]+1, Dig[edge[i].to]=(Dig[now]*10%M+edge[i].val)%M, DFS(edge[i].to,now); } inline LL Get(int now,int last) { LL re=hash[Dig[now]]; for (int i=head[now]; i; i=edge[i].next) if (edge[i].to!=last && !visit[edge[i].to]) Dig[edge[i].to]=(edge[i].val*power[deep[now]]%M+Dig[now])%M, deep[edge[i].to]=deep[now]+1, re+=Get(edge[i].to,now); return re; } inline void Divide(int now) { visit[now]=1; hash.clear(); hash[0]--; Dig[now]=0LL,deep[now]=0; DFS(now,0); ans+=Get(now,0); for (int i=head[now]; i; i=edge[i].next) if (!visit[edge[i].to]) hash.clear(),hash[0]--, Dig[edge[i].to]=edge[i].val%M,deep[edge[i].to]=1, DFS(edge[i].to,now), ans-=Get(edge[i].to,now); for (int i=head[now]; i; i=edge[i].next) if (!visit[edge[i].to]) Sz=size[edge[i].to],f[root=0]=N, Getroot(edge[i].to,now),Divide(root); } } using namespace TreeDivide; int main() { N=read(),M=read(); for (int x,y,z,i=1; i<=N-1; i++) x=read()+1,y=read()+1,z=read(),InsertEdge(x,y,z); for (int i=0; i<=N; i++) power[i]=Pow(10,i),Inv[i]=inv(power[i]); Sz=N; f[root=0]=N+1; Getroot(1,0); Divide(root); printf("%I64d\n",ans); return 0; }
CDQ分治
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> using namespace std; inline int read() { int x=0,f=1; char ch=getchar(); while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();} while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();} return x*f; } #define MAXN 200010 int N,cnt; struct QNode{ int opt,id,x,y,v,as; bool operator < (const QNode & A) const { return x<A.x; } //{return (x==A.x&&y==A.y)? opt<A.opt:(x==A.x? y<A.y:x<A.x);} }Q[MAXN<<2]; int tree[500010]; inline int lowbit(int x) {return x&-x;} inline void Modify(int x,int d) { for (int i=x; i<=N; i+=lowbit(i)) tree[i]+=d;} inline int Query(int x) {int re=0; for (int i=x; i; i-=lowbit(i)) re+=tree[i]; return re;} int ans[MAXN]; inline void CDQ(int l,int r) { if (l==r) return; // printf("begin<%d %d>\n",l,r); int mid=(l+r)>>1; CDQ(l,mid); CDQ(mid+1,r); sort(Q+l,Q+mid+1); sort(Q+mid+1,Q+r+1); int i=l,j=mid+1,pos=0; while (j<=r) { while (Q[i].opt==2 && i<=mid) i++; while (Q[j].opt==1 && j<=r) j++; if (i<=mid && Q[i].x<=Q[j].x) Modify(Q[i].y,Q[i].v),pos=i++; else if (j<=r) ans[Q[j].as]+=Query(Q[j].y)*Q[j].v,j++; // printf("%d %d\n",i,j); } for (int k=l; k<=pos; k++) if (Q[k].opt==1) Modify(Q[k].y,-Q[k].v); // printf("end<%d %d>\n",l,r); } int main() { N=read(); int ID=0,as=0,opt; while (scanf("%d",&opt) && opt!=3) { ID++; if (opt==1) { int x=read(),y=read(),z=read(); Q[++cnt].opt=opt,Q[cnt].id=ID,Q[cnt].x=x,Q[cnt].y=y,Q[cnt].v=z; continue; } int x1=read(),y1=read(),x2=read(),y2=read(); as++; Q[++cnt].opt=opt,Q[cnt].id=ID,Q[cnt].x=x2,Q[cnt].y=y2,Q[cnt].v=+1,Q[cnt].as=as; Q[++cnt].opt=opt,Q[cnt].id=ID,Q[cnt].x=x1-1,Q[cnt].y=y1-1,Q[cnt].v=+1,Q[cnt].as=as; Q[++cnt].opt=opt,Q[cnt].id=ID,Q[cnt].x=x1-1,Q[cnt].y=y2,Q[cnt].v=-1,Q[cnt].as=as; Q[++cnt].opt=opt,Q[cnt].id=ID,Q[cnt].x=x2,Q[cnt].y=y1-1,Q[cnt].v=-1,Q[cnt].as=as; } // for (int i=1; i<=cnt; i++) printf("%d %d %d %d %d\n",i,Q[i].opt,Q[i].x,Q[i].y,Q[i].v); CDQ(1,cnt); for (int i=1; i<=as; i++) printf("%d\n",ans[i]); return 0; }
莫队算法 序列带修 树上不带修&带修
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> using namespace std; int read() { int x=0,f=1; char ch=getchar(); while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();} while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();} return x*f; } #define maxm 20010 #define maxc 1000100 int n,m,bll,ans[maxm],nl=1,nr=0,nt=0,an,pos[maxm],num[maxc],a[maxm],aa[maxm]; bool visit[maxc]; struct Asknode { int l,r,t,id; bool operator < (const Asknode & A) const { if (pos[l]==pos[A.l] && pos[r]==pos[A.r]) return t<A.t; else if (pos[l]==pos[A.l]) return r<A.r; else return l<A.l; } }q[maxm];int qn; struct Changenode{int x,c,t,pre;}ch[maxm];int cn; void move(int x) { if (visit[x]) {num[a[x]]--;if (num[a[x]]==0) an--; visit[x]=0;} else {num[a[x]]++;if (num[a[x]]==1) an++; visit[x]=1;} } void movedown(int T) { int x=ch[T].x,c=ch[T].c; if (visit[x]) {num[a[x]]--; if (num[a[x]]==0) an--; a[x]=c; num[c]++; if (num[c]==1) an++;} else a[x]=c; } void moveforward(int T) { int x=ch[T].x,c=ch[T].pre; if (visit[x]) {num[a[x]]--; if (num[a[x]]==0) an--; a[x]=c; num[c]++; if (num[c]==1) an++;} else a[x]=c; } void work(int x) { int L=q[x].l,R=q[x].r,id=q[x].id,T=q[x].t; while (nl<L) move(nl),nl++; while (nl>L) nl--,move(nl); while (nr<R) nr++,move(nr); while (nr>R) move(nr),nr--; while (nt<T) nt++,movedown(nt); while (nt>T) moveforward(nt),nt--; ans[id]=an; } int main() { n=read(),m=read(); bll=int(sqrt(n)); for (int i=1; i<=n; i++) aa[i]=a[i]=read(),pos[i]=(i-1)/bll+1; for (int i=1; i<=m; i++) { char opt[5]; scanf("%s",opt); int x=read(),y=read(); if (opt[0]=='Q') qn++,q[qn].id=qn,q[qn].l=x,q[qn].r=y,q[qn].t=cn; if (opt[0]=='R') cn++,ch[cn].t=i,ch[cn].x=x,ch[cn].c=y,ch[cn].pre=aa[x],aa[x]=y; } sort(q+1,q+qn+1); for (int i=1; i<=qn; i++) work(i); for (int i=1; i<=qn; i++) printf("%d\n",ans[i]); return 0; }
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> using namespace std; int read() { int x=0;char ch=getchar(); while(ch<'0'||ch>'9') ch=getchar(); while(ch>='0'&&ch<='9') {x=x*10+ch-'0';ch=getchar();} return x; } #define maxn 50100 #define maxq 100100 int n,m,fk,knum,ans,root; struct Edgenode{int to,next;}edge[maxn<<1]; int head[maxn],cnt=1; void add(int u,int v) {cnt++;edge[cnt].next=head[u];head[u]=cnt;edge[cnt].to=v;} void insert(int u,int v) {add(u,v); add(v,u);} int deep[maxn],father[maxn][25],dfsx,stack[maxn],top,rt[maxn],an[maxq],p[maxn]; struct Pointnode{int dfs,col;}po[maxn]; struct Asknode { int a,b,u,v,id; bool operator < (const Asknode & A) const { if(rt[u]==rt[A.u]) return po[v].dfs<po[A.v].dfs; else return rt[u]<rt[A.u]; } }q[maxq]; bool visit[maxn]; int DFS(int now) { int size=0; po[now].dfs=++dfsx; for (int i=1; i<=20; i++) if (deep[now]>=(1<<i)) father[now][i]=father[father[now][i-1]][i-1]; for (int i=head[now]; i; i=edge[i].next) if (edge[i].to!=father[now][0]) { deep[edge[i].to]=deep[now]+1; father[edge[i].to][0]=now; size+=DFS(edge[i].to); if (size>=fk) { knum++; for(int j=1; j<=size; j++) rt[stack[top--]]=knum; size=0; } } stack[++top]=now; return size+1; } int LCA(int x,int y) { if (deep[x]<deep[y]) swap(x,y); int dd=deep[x]-deep[y]; for (int i=0; i<=20; i++) if (dd&(1<<i) && dd>=(1<<i)) x=father[x][i]; for (int i=20; i>=0; i--) if (father[x][i]!=father[y][i]) x=father[x][i],y=father[y][i]; if (x==y) return x; else return father[x][0]; } void reserv(int x) { if (!visit[x]) {visit[x]=1; p[po[x].col]++; if (p[po[x].col]==1) ans++;} else {visit[x]=0; p[po[x].col]--; if (p[po[x].col]==0) ans--;} } void work(int u,int v) { while (u!=v) if (deep[u]>deep[v]) reserv(u),u=father[u][0]; else reserv(v),v=father[v][0]; } int main() { n=read(),m=read(); fk=sqrt(n); for (int i=1; i<=n; i++) po[i].col=read(); for (int u,v,i=1; i<=n; i++) { u=read(),v=read(); if (!u) root=v; else if (!v) root=u; else insert(u,v); } DFS(root); knum++; while (top) rt[stack[top--]]=knum; for (int i=1; i<=m; i++) { q[i].u=read();q[i].v=read();q[i].a=read();q[i].b=read();q[i].id=i; if (po[q[i].u].dfs>po[q[i].v].dfs) swap(q[i].u,q[i].v); } sort(q+1,q+m+1); int T=LCA(q[1].u,q[1].v); work(q[1].u,q[1].v); reserv(T); an[q[1].id]=ans; if (p[q[1].a] && p[q[1].b] && q[1].a!=q[1].b) an[q[1].id]--; reserv(T); for (int i=2; i<=m; i++) { work(q[i-1].u,q[i].u); work(q[i-1].v,q[i].v); T=LCA(q[i].u,q[i].v); reserv(T); an[q[i].id]=ans; if(p[q[i].a] && p[q[i].b] && q[i].a!=q[i].b) an[q[i].id]--; reserv(T); } for (int i=1; i<=m; i++) printf("%d\n",an[i]); return 0; }
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> using namespace std; #define maxn 100010 #define maxm 100010 #define maxq 100010 int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } int n,m,Q,fk,knum,rt[maxn];long long V[maxm],W[maxn],an[maxn],C[maxn],ans; struct Edgenode{int to,next;}edge[maxn<<1]; int head[maxn],cnt; void add(int u,int v) {cnt++;edge[cnt].next=head[u];head[u]=cnt;edge[cnt].to=v;} void insert(int u,int v) {add(u,v);add(v,u);} int stack[maxn],top,dfsx,dfs[maxn],deep[maxn],father[maxn][25]; int DFS(int now) { int size=0; dfs[now]=++dfsx; for (int i=1; i<=20; i++) if (deep[now]>=(1<<i)) father[now][i]=father[father[now][i-1]][i-1]; for (int i=head[now]; i; i=edge[i].next) if (edge[i].to!=father[now][0]) { deep[edge[i].to]=deep[now]+1; father[edge[i].to][0]=now; size+=DFS(edge[i].to); if (size>=fk) { knum++; for (int j=1; j<=size; j++) rt[stack[top--]]=knum; size=0; } } stack[++top]=now; return size+1; } int LCA(int x,int y) { if (deep[x]<deep[y]) swap(x,y); int dd=deep[x]-deep[y]; for (int i=0; i<=20; i++) if (dd&(1<<i) && dd>=(1<<i)) x=father[x][i]; for (int i=20; i>=0; i--) if (father[x][i]!=father[y][i]) x=father[x][i],y=father[y][i]; if (x==y) return x; else return father[x][0]; } bool visit[maxn]; int num[maxn]; void Reverse(int x) { if (visit[x]) {visit[x]=0; ans-=W[num[C[x]]]*V[C[x]]; num[C[x]]--;} else {visit[x]=1; num[C[x]]++; ans+=W[num[C[x]]]*V[C[x]];} // printf("%d\n",ans); } void Change(int x,int y) { if (visit[x]) Reverse(x),C[x]=y,Reverse(x); else C[x]=y; } void work(int x,int y) { while (x!=y) if (deep[x]>deep[y]) Reverse(x),x=father[x][0]; else Reverse(y),y=father[y][0]; } struct Asknode { int a,b,t,id; bool operator < (const Asknode & A) const { if (rt[a]==rt[A.a] && rt[b]==rt[A.b]) return t<A.t; else if (rt[a]==rt[A.a]) return rt[b]<rt[A.b]; return rt[a]<rt[A.a]; } }q[maxq];int numq; struct Changenode{int a,b,t,p;}ch[maxq];int numc,p[maxq]; int main() { n=read(),m=read(),Q=read(); fk=pow(n,2.0/3)*0.5; for (int i=1; i<=m; i++) V[i]=read(); for (int i=1; i<=n; i++) W[i]=read(); for (int u,v,i=1; i<=n-1; i++) u=read(),v=read(),insert(u,v); for (int i=1; i<=n; i++) C[i]=read(); for (int i=1; i<=n; i++) p[i]=C[i]; DFS(1); // puts("OK"); // for (int i=1; i<=n; i++) printf("%d %d %d %d\n",V[i],W[i],dfs[i],p[i]); // for (int i=1; i<=n; i++) printf("%d ",rt[i]); puts(""); // puts("OK"); while (top) rt[stack[top--]]=knum; for (int i=1; i<=Q; i++) { int opt=read(),a=read(),b=read(); if (opt) {if (dfs[a]>dfs[b]) swap(a,b); numq++;q[numq].a=a; q[numq].b=b; q[numq].t=numc; q[numq].id=numq;} else {numc++;ch[numc].a=a;ch[numc].b=b;ch[numc].t=i;ch[numc].p=p[a]; p[a]=b;} } sort(q+1,q+numq+1); //for (int i=1; i<=numq; i++) printf("%d %d %d %d\n",q[i].a,q[i].b,q[i].id,q[i].t); for (int i=1; i<=q[1].t; i++) Change(ch[i].a,ch[i].b); work(q[1].a,q[1].b); int T=LCA(q[1].a,q[1].b); Reverse(T); an[q[1].id]=ans; Reverse(T); for (int i=2; i<=numq; i++) { for(int j=q[i-1].t+1; j<=q[i].t; j++) Change(ch[j].a,ch[j].b); for(int j=q[i-1].t; j>q[i].t; j--) Change(ch[j].a,ch[j].p); work(q[i-1].a,q[i].a); work(q[i-1].b,q[i].b); T=LCA(q[i].a,q[i].b); Reverse(T); an[q[i].id]=ans; Reverse(T); } for (int i=1; i<=numq; i++) printf("%lld\n",an[i]); return 0; }
——It's a lonely path. Don't make it any lonelier than it has to be.