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.
浙公网安备 33010602011771号