【模板】其他算法

随机化

模拟退火
//Author:RingweEH
//P5544 [JSOI2016]炸弹攻击1
const int N=11,M=1010;
const double delta=0.996,Te=1e-10;          //D和最终温度
int n,m,x[N],y[N],r[N],p[M],q[M],R,ansout=0;
double ansx,ansy;
 
double dis( double ax,double ay,double bx,double by )		//求两点间距离
{
    double res=(bx-ax)*(bx-ax)+(by-ay)*(by-ay);
    res=sqrt(res);
    return res;
}
 
int calc( double xx,double yy )			//估价函数
{
    double nowr=R;
    for ( int i=1; i<=n; i++ )
        nowr=min( nowr,dis(xx,yy,x[i],y[i])-(double)r[i] );
    int cnt=0;
    for ( int i=1; i<=m; i++ )
        if ( dis(xx,yy,p[i],q[i])<=nowr ) cnt++;
    return cnt;
}
 
void SA()
{
    double T=6000;		//初始温度
    int ans=0;
    while ( T>Te )
    {
        double nowx=ansx+(rand()*2-RAND_MAX)*T;
        double nowy=ansy+(rand()*2-RAND_MAX)*T;
        int nowans=calc( nowx,nowy );
        int DelE=nowans-ans;
        if ( DelE>0 ) ansx=nowx,ansy=nowy,ans=nowans,ansout=max( ansout,ans );
        //更优的解,必然接受
        else if ( exp(DelE/sqrt(T))>(double)rand()/1215 ) ansx=nowx,ansy=nowy,ans=nowans;
        //按概率接受,保证了越到后期,和最优解的差距越大,越难被接受
        T*=delta;
    }
}
 
int main()
{
    srand(time(0)); ansx=ansy=0;
    n=read(); m=read(); R=read();
    for ( int i=1; i<=n; i++ )
        x[i]=read(),y[i]=read(),r[i]=read();
    for ( int i=1; i<=m; i++ )
        p[i]=read(),q[i]=read(),ansx+=x[i],ansy+=y[i];
    
    ansx/=m; ansy/=m; ansout=calc( ansx,ansy );
    while ( (double)clock()/CLOCKS_PER_SEC<=0.85 ) SA();
 
    printf( "%d",ansout );
}

分治

整体二分
//Author: RingweEH
//P2617 Dynamic Rankings
#define lowbit(x) ((x)&(-x))
const int N=1e5+10,INF=0x3f3f3f3f;
int n,m,a[N],tr[N],ans[N],tot=0;
struct Operation
{ 
	int tim,opt,l,r,val; 
	Operation( int _tim=0,int _opt=0,int _l=0,int _r=0,int _val=0 )
		: tim(_tim),opt(_opt),l(_l),r(_r),val(_val) {}
//opt=0(insert),1(delete),2(query)
//val:insert x,query rk k;
}q[N*3],le[N*3],ri[N*3];
void Add( int x,int v ) { for(;x<=n;x+=lowbit(x)) tr[x]+=v; }
int Query(int x){int res=0;for(;x;x-=lowbit(x))res+=tr[x];return res;}

void Solve( int ql,int qr,int l,int r )
{//二分询问和答案,插入删除直接做,查询如果比rk小那么答案就在右区间,否则在左区间。
	if ( l==r )
	{
		for ( int i=ql; i<=qr; i++ )
			if ( q[i].opt==2 ) ans[q[i].tim]=l;
		return;
	}
	int mid=(l+r)>>1,lcnt=0,rcnt=0,i,tmp;
	for ( i=ql; i<=qr; i++ )
	{
		if ( q[i].opt==0 ) //insert
		{
			if ( q[i].val<=mid ) le[++lcnt]=q[i],Add(q[i].l,1);
			else ri[++rcnt]=q[i];
		}
		else if ( q[i].opt==1 ) //detele
		{
			if ( q[i].val<=mid ) le[++lcnt]=q[i],Add(q[i].l,-1);
			else ri[++rcnt]=q[i];
		}
		else	//query
		{
			tmp=Query(q[i].r)-Query(q[i].l-1);
			if ( tmp<q[i].val ) q[i].val-=tmp,ri[++rcnt]=q[i];
			else le[++lcnt]=q[i];
		}
	}
	for ( i=1; i<=lcnt; i++ ) 	//recover
	{
		q[ql+i-1]=le[i];
		if ( le[i].opt==0 ) Add(le[i].l,-1);
		else if ( le[i].opt==1 ) Add(le[i].l,1);
	}
	for ( i=1; i<=rcnt; i++ ) q[ql+lcnt+i-1]=ri[i];
	if ( lcnt ) Solve(ql,ql+lcnt-1,l,mid);
	if ( rcnt ) Solve(ql+lcnt,qr,mid+1,r);
}

int main()
{
	scanf("%d%d",&n,&m);
	for ( int i=1; i<=n; i++ ) scanf("%d",&a[i]),q[++tot]=Operation(0,0,i,i,a[i]);

	int lcnt=0,rcnt=0,x,y,rk; char s[2];
	for ( int i=1; i<=m; i++ )
	{
		scanf( "%s",s );
		if ( s[0]=='C' )
		{
			lcnt++; scanf( "%d%d",&x,&y ); 
			q[++tot]=Operation(lcnt,1,x,x,a[x]);
			q[++tot]=Operation(lcnt,0,x,x,y);
			a[x]=y;
		}
		if ( s[0]=='Q' )
		{
			rcnt++; scanf("%d%d%d",&x,&y,&rk);
			q[++tot]=Operation(rcnt,2,x,y,rk);
		}
	}
	Solve(1,tot,0,INF);

	for ( int i=1 ;i<=rcnt; i++ ) printf("%d\n",ans[i] );

	return 0;
}
CDQ分治(三维偏序)
//Author: RingweEH
//P3810 【模板】三维偏序(陌上花开)
#define lowbit(x) ((x)&(-x))
const int N=1e5+10,K=2e5+10;
struct Node{ int x,y,z,res,sam; }a[N],b[N];
int n,m,f[K],tr[K],k;

bool cmp3(Node t1,Node t2){return (t1.x==t2.x) ? ((t1.y==t2.y) ? t1.z<t2.z:t1.y<t2.y):t1.x<t2.x;}
bool cmp2(Node t1,Node t2){return (t1.y==t2.y) ? t1.z<t2.z : t1.y<t2.y; }
void Add( int x,int v ) { for ( ;x<=k;x+=lowbit(x))tr[x]+=v; }
int Query( int x ) { int res=0;for(;x;x-=lowbit(x))res+=tr[x]; return res;}

void CDQ_Conq( int l,int r )
{
    if ( l==r ) return;
    int mid=(l+r)>>1,i=mid+1,j=l;
    CDQ_Conq(l,mid); CDQ_Conq(mid+1,r);
    sort(a+l,a+mid+1,cmp2); sort(a+mid+1,a+r+1,cmp2);
    for ( ; i<=r; i++ )
    {
        while ( a[j].y<=a[i].y && j<=mid ) Add(a[j].z,a[j].sam),j++;
        a[i].res+=Query(a[i].z);
    }
    for ( i=l; i<j; i++ ) Add(a[i].z,-a[i].sam);
}

int main()
{
    m=read(); k=read(); n=0;
    for ( int i=1; i<=m; i++ ) b[i].x=read(),b[i].y=read(),b[i].z=read();

    sort(b+1,b+1+m,cmp3); int cnt=0;
    for ( int i=1; i<=m; i++ )
    {
        cnt++;
        if ( (b[i].x^b[i+1].x) || (b[i].y^b[i+1].y) || (b[i].z^b[i+1].z) )
            a[++n]=b[i],a[n].sam=cnt,cnt=0,a[n].res=0;
    }
    CDQ_Conq(1,n);

    for ( int i=1; i<=n; i++ ) f[a[i].res+a[i].sam-1]+=a[i].sam;
    for ( int i=0; i<m; i++ ) printf("%d\n",f[i] );

    return 0;
}
CDQ套CDQ(四维偏序)
//Author: RingweEH
//P5621 [DBOI2019]德丽莎世界第一可爱
#define lowbit(x) ((x)&(-x))
const int N=5e4+10;
struct Node { int a,b,c,d,id; bool typ; ll mx,val; }a[N],b[N];
int n,id1[N],id2[N],tmp[N],tot;
ll tr[N];

bool operator == ( Node t1,Node t2 )
{ return t1.a==t2.a && t1.b==t2.b && t1.c==t2.c && t1.d==t2.d; }

bool cmp1( Node t1,Node t2 )
{
	return (t1.a^t2.a) ? t1.a<t2.a :
		   (t1.b^t2.b) ? t1.b<t2.b :
	       (t1.c^t2.c) ? t1.c<t2.c :
	       t1.d<t2.d;
}
bool cmp2( Node t1,Node t2 )
{
	return (t1.b^t2.b) ? t1.b<t2.b :
	       (t1.c^t2.c) ? t1.c<t2.c :
	       (t1.d^t2.d) ? t1.d<t2.d :
	       t1.a<t2.a;
}
bool cmp3( Node t1,Node t2 )
{
	return (t1.c^t2.c) ? t1.c<t2.c :
	       (t1.d^t2.d) ? t1.d<t2.d :
	       (t1.a^t2.a) ? t1.a<t2.a :
	       t1.b<t2.b;
}

void Add( int x,ll val ){ for (;x<=tot; x+=lowbit(x)) if (tr[x]<val) tr[x]=val;else return;}
ll Query( int x ) { ll res=0;for(;x;x-=lowbit(x)) bmax(res,tr[x]); return res;}
void Clear(int x){ for (;x<=tot;x+=lowbit(x)) if ( tr[x] ) tr[x]=0; else return; }

void CDQ_Son( int l,int r )
{
	if ( l==r ) return;
	int mid=(l+r)>>1; CDQ_Son(l,mid);
	sort(a+l,a+mid+1,cmp3); sort(a+mid+1,a+r+1,cmp3);
	int i=mid+1,j=l;
	while ( i<=r && j<=mid )
	{
		if ( a[j].c<=a[i].c ) 
		{ if ( a[j].typ ) Add( a[j].d,a[j].mx ); j++; }
		else 
		{ if ( !a[i].typ ) bmax( a[i].mx,Query(a[i].d)+a[i].val); i++; }
	}
	while ( i<=r ) { if ( !a[i].typ ) bmax( a[i].mx,Query(a[i].d)+a[i].val); i++; }
	for ( int i=l; i<j; i++ ) if ( a[i].typ ) Clear(a[i].d);
	for ( int i=l; i<=r; i++ ) b[id2[a[i].id]]=a[i];
	for ( int i=l; i<=r; i++ ) a[i]=b[i];
	CDQ_Son(mid+1,r);
}
void CDQ( int l,int r )
{
	if ( l==r ) return;
	int mid=(l+r)>>1; CDQ(l,mid);
	for ( int i=l; i<=r; i++ ) a[i].typ=(i<=mid);
	sort( a+l,a+r+1,cmp2 );
	for ( int i=l; i<=r; i++ ) id2[a[i].id]=i;
	CDQ_Son(l,r);
	for ( int i=l; i<=r; i++ ) b[id1[a[i].id]]=a[i];
	for ( int i=l; i<=r; i++ ) a[i]=b[i];
	CDQ(mid+1,r);
}

int main()
{
	n=read();
	for ( int i=1; i<=n; i++ )
		a[i].a=read(),a[i].b=read(),a[i].c=read(),a[i].d=read(),a[i].val=read(),tmp[i]=a[i].d;

	sort(tmp+1,tmp+n+1);
	tot=unique(tmp+1,tmp+1+n)-tmp-1; 
	sort(a+1,a+1+n,cmp1);
	for ( int i=1; i<=n; i++ ) 
		a[i].d=lower_bound(tmp+1,tmp+tot+1,a[i].d)-tmp;
	int cnt=0;
	for ( int i=1; i<=n; i++ )
		if ( a[i]==a[i-1] ) a[cnt].val+=max(a[i].val,0ll);
		else a[++cnt]=a[i];
	n=cnt;
	for ( int i=1; i<=n; i++ )
		a[i].mx=a[i].val,a[i].id=id1[i]=i;
	CDQ(1,n);

	ll ans=-1e18;
	for ( int i=1; i<=n; i++ ) bmax( ans,a[i].mx );
	printf("%lld\n",ans );

	return 0;
}

DDP
//Author: RingweEH
//P4719 【模板】"动态 DP"&动态树分治
#include <cstdio>
#include <cstring>
#include <algorithm>
#define ll long long
#define db double
using namespace std;
int min( int a,int b ) { return a<b ? a : b; }
int max( int a,int b ) { return a>b ? a : b; }
void bmax( int &a,int b ) { a=(a>b) ? a : b; }
void bmin( int &a,int b ) { a=(a<b) ? a : b; }
const int L=1<<20;
char buf[L],*p1,*p2;
#define getchar() (p1==p2?(p2=buf+fread(p1=buf,1,L,stdin),p1==p2?EOF:*p1++):*p1++)
int read()
{
    int x=0,w=1; char ch=getchar();
    while ( ch>'9' || ch<'0' ) { if ( ch=='-' ) w=-1; ch=getchar(); }
    while ( ch<='9' && ch>='0' ) x=x*10+ch-'0',ch=getchar();
    return x*w;
}

#define ls pos<<1
#define rs pos<<1|1
const int N=1e5+1,M=2e5+1,NM=4e5+1,INF=0x3f3f3f3f;
int tot,head[N],n,m,tim,f[N][2];
int a[N],fa[N],siz[N],dep[N],dfn[N],id[N];
int wson[N],top[N],ed[N];
struct Matrix
{
    int mat[2][2];
    Matrix(){memset(mat,-0x3f,sizeof(mat));}
}val[N];
Matrix operator * ( Matrix A,Matrix B )
{
    Matrix res;
    for ( int k=0; k<2; k++ )
        for ( int i=0; i<2; i++ )
            for ( int j=0; j<2; j++ )
                bmax(res.mat[i][j],A.mat[i][k]+B.mat[k][j]);
    return res;
}
struct Edge { int to,nxt; }e[M];
void Adde( int u,int v ) { e[++tot].to=v; e[tot].nxt=head[u]; head[u]=tot; }
struct SegmentTree
{
    int le[NM],ri[NM];
    Matrix tr[NM];
    inline void Pushup( int pos ) { tr[pos]=tr[ls]*tr[rs]; }
    void Build( int pos,int l,int r )
    {
        le[pos]=l; ri[pos]=r;
        if ( l==r ) { tr[pos]=val[dfn[l]]; return; }
        int mid=l+r>>1;
        Build(ls,l,mid); Build(rs,mid+1,r); Pushup(pos);
    }
    void Modify( int pos,int x )
    {
        if ( le[pos]==ri[pos] ) { tr[pos]=val[dfn[x]]; return; }
        int mid=(le[pos]+ri[pos])>>1;
        (x<=mid) ? Modify(ls,x) : Modify(rs,x); Pushup(pos);
    }
    Matrix Query( int pos,int L,int R )
    {
        if ( le[pos]==L && ri[pos]==R ) return tr[pos];
        int mid=(le[pos]+ri[pos])>>1;
        if ( R<=mid ) return Query(ls,L,R);
        else if ( L>mid ) return Query(rs,L,R);
        else return Query(ls,L,mid)*Query(rs,mid+1,R);
    }
}Tr;

void DFS1( int u )
{
    siz[u]=1;
    for ( int i=head[u]; i; i=e[i].nxt )
    {
        int v=e[i].to;
        if ( v==fa[u] ) continue;
        fa[v]=u; dep[v]=dep[u]+1; DFS1(v);
        siz[u]+=siz[v];
        if ( siz[v]>siz[wson[u]] ) wson[u]=v;
    }
}

void DFS2( int u,int lin )
{
    id[u]=++tim; dfn[tim]=u; top[u]=lin; bmax(ed[lin],tim);
    f[u][0]=0; f[u][1]=a[u];
    val[u].mat[0][0]=val[u].mat[0][1]=0; val[u].mat[1][0]=a[u];
    if ( wson[u]^0 )
    {
        DFS2(wson[u],lin);
        f[u][0]+=max(f[wson[u]][0],f[wson[u]][1] ); f[u][1]+=f[wson[u]][0];
    }
    for ( int i=head[u]; i; i=e[i].nxt )
    {
        int v=e[i].to;
        if ( v==fa[u] || v==wson[u] ) continue;
        DFS2(v,v);
        f[u][0]+=max(f[v][0],f[v][1]); f[u][1]+=f[v][0];
        val[u].mat[0][1]=val[u].mat[0][0]+=max(f[v][0],f[v][1]);
        val[u].mat[1][0]+=f[v][0];
    }
}

void Update( int x,int y )
{
    val[x].mat[1][0]+=y-a[x]; a[x]=y;
    Matrix pre,las;
    while ( x^0 )
    {
        pre=Tr.Query(1,id[top[x]],ed[top[x]]);
        Tr.Modify(1,id[x]);
        las=Tr.Query(1,id[top[x]],ed[top[x]]);
        x=fa[top[x]];
        val[x].mat[0][0]+=max(las.mat[0][0],las.mat[1][0])-max(pre.mat[0][0],pre.mat[1][0]);
        val[x].mat[0][1]=val[x].mat[0][0]; val[x].mat[1][0]+=las.mat[0][0]-pre.mat[0][0];
    }
}

int main()
{
//freopen( "exam.in","r",stdin );

    n=read(); m=read();
    for ( int i=1; i<=n; i++ ) a[i]=read();
    for ( int i=1,u,v; i<n; i++ ) u=read(),v=read(),Adde(u,v),Adde(v,u);

    DFS1(1); DFS2(1,1);
    Tr.Build(1,1,n); Matrix ans;
    for ( int i=1,x,y; i<=m; i++ )
    {
        x=read(); y=read();
        Update(x,y); ans=Tr.Query(1,id[1],ed[1]);
        printf("%d\n",max(ans.mat[0][0],ans.mat[1][0]) );
    }

    return 0;
}
posted @ 2020-11-12 14:01  MontesquieuE  阅读(41)  评论(0编辑  收藏  举报