NOIP2013

转圈游戏

Link
快速幂。

#include<cstdio>
int n;
int mul(int a,int b){return 1ll*a*b%n;}
int power(int k){int a=10,r=1;for(;k;k>>=1,a=mul(a,a))if(k&1)r=mul(a,r);return r;}
int main(){int m,k,x;scanf("%d%d%d%d",&n,&m,&k,&x),printf("%d",(x+mul(m,power(k)))%n);}

火柴排队

Link
转化部分挺妙的。
首先我们知道排序后第(i)大的(a)会对应第(i)大的(j)
我们把(a,b)序列离散化得到(c,d)。并令(p_{c_i}=d_i)
我们要做的是让(p_i=i)
而交换(a)(b)序列中的两个元素等同于交换两个(p)
所以答案就是(p)的逆序对数,树状数组求即可。

#include<bits/stdc++.h>
using namespace std;
const int N=1000001,P=99999997;
int read(){int x=0,c=getchar();while(!isdigit(c))c=getchar();while(isdigit(c))x=x*10+c-48,c=getchar();return x;}
int n,a[N],b[N],c[N],d[N],q[N],t[N];
void add(int p,int v){for(;p<=n;p+=p&-p)t[p]+=v;}
int ask(int p){int s=0;for(;p;p^=p&-p)s+=t[p];return s;}
int main()
{
    n=read();int ans=0,i;
    for(i=1;i<=n;++i) a[c[i]=i]=read();
    for(i=1;i<=n;++i) b[d[i]=i]=read();
    sort(c+1,c+n+1,[](int i,int j){return a[i]<a[j];});
    sort(d+1,d+n+1,[](int i,int j){return b[i]<b[j];});
    for(i=1;i<=n;++i) q[c[i]]=d[i];
    for(i=n;i;--i) (ans+=ask(q[i]-1))%=P,add(q[i],1);
    printf("%d",ans);
}

货车运输

Link
直接上Kruskal重构树。当然倍增也是可以的。

#include<bits/stdc++.h>
#define open(file) freopen(file".in","r",stdin),freopen(file".out","w",stdout)
#define N 200007
using namespace std;
namespace IO
{
    char ibuf[(1<<21)+1],obuf[(1<<21)+1],st[15],*iS,*iT,*oS=obuf,*oT=obuf+(1<<21);
    char Get() { return (iS==iT? (iT=(iS=ibuf)+fread(ibuf,1,(1<<21)+1,stdin),(iS==iT? EOF:*iS++)):*iS++); }
    void Flush() { fwrite(obuf,1,oS-obuf,stdout),oS=obuf; }
    void Put(char x) { *oS++=x; if(oS==oT) Flush(); }
    int read(){int x=0;char ch=Get();while(ch>57||ch<48)ch=Get();while(ch>=48&&ch<=57)x=x*10+(ch^48),ch=Get();return x;}
    void write(int x) {int top=0; if(!x) Put('0'); while(x) st[++top]=(x%10)+48,x/=10; while(top) Put(st[top--]); Put('
'); }
}
using namespace IO;
void print(){Put('-'),Put('1'),Put('
');}
struct Edge{int u,v,w;}edge[N];
int operator<(Edge a,Edge b){return a.w>b.w;}
int head[N],tot,Fa[N],ver[N],Next[N],val[N],vis[N],dep[N],fa[N],size[N],son[N],top[N];
void add(int u,int v){ver[++tot]=v,Next[tot]=head[u],head[u]=tot;}
int Find(int x){return x==Fa[x]? x:Fa[x]=Find(Fa[x]);}
void dfs(int u,int Fa)
{
    size[u]=vis[u]=1;
    for(int i=head[u],v;i;i=Next[i]) if((v=ver[i])^Fa) dep[v]=dep[u]+1,fa[v]=u,dfs(v,u),size[u]+=size[v],son[u]=size[v]>size[son[u]]? v:son[u];
}
void Dfs(int u,int Top)
{
    top[u]=Top;
    if(son[u]) Dfs(son[u],Top);
    for(int i=head[u],v;i;i=Next[i]) if((v=ver[i])^son[u]&&v^fa[u]) Dfs(v,v);
}
int LCA(int u,int v)
{
    while(top[u]^top[v]) dep[top[u]]>dep[top[v]]? u=fa[top[u]]:v=fa[top[v]];
    return dep[u]>dep[v]? v:u;
}
int main()
{
    int n=read(),m=read(),cnt=n,i,Q,u,v;
    for(i=1;i<=m;++i) edge[i]=Edge{read(),read(),read()};
    sort(edge+1,edge+m+1);
    for(i=1;i<=n;++i) Fa[i]=i;
    for(i=1;i<=m;++i) if((u=Find(edge[i].u))^(v=Find(edge[i].v))) val[++cnt]=edge[i].w,Fa[cnt]=Fa[u]=Fa[v]=cnt,add(u,cnt),add(cnt,u),add(v,cnt),add(cnt,v);
    for(u=1;u<=cnt;++u) if(!vis[u]) dfs(v=Find(u),0),Dfs(v,v);
    for(Q=read();Q;--Q) u=read(),v=read(),Find(u)^Find(v)? print():write(val[LCA(u,v)]);
    return Flush(),0;
}

积木大赛

Link
略了。

花匠

Link
树状数组优化dp是一个非常不错的方式。
其实可以贪心优化至(O(n))
假如我们现在是一个“上-下”的形式,那么下一个需要接一个比当前大的。
如果下一个比现在这个大,我们就直接接上。
如果下一个比现在这个小,我们就拿它替换掉当前这个。
代码写的是每个有一个可能的区间。

#include<cstdio>
#include<cctype>
namespace IO
{
    char ibuf[(1<<21)+1],obuf[(1<<21)+1],st[15],*iS,*iT,*oS=obuf,*oT=obuf+(1<<21);
    char Get(){return (iS==iT? (iT=(iS=ibuf)+fread(ibuf,1,(1<<21)+1,stdin),(iS==iT? EOF:*iS++)):*iS++);}
    void Flush(){fwrite(obuf,1,oS-obuf,stdout),oS=obuf;}
    void Put(char x){*oS++=x;if(oS==oT)Flush();}
    int read(){int x=0;char ch=Get();while(ch>57||ch<48)ch=Get();while(ch>=48&&ch<=57)x=x*10+(ch^48),ch=Get();return x;}
    void write(int x){int top=0;if(!x)Put('0');while(x)st[++top]=(x%10)+48,x/=10;while(top)Put(st[top--]);Put('
');}
}
using namespace IO;
int max(int a,int b){return a>b? a:b;}
const int N=1000001;
int l[N],r[N];
int main()
{
	int n=read(),i,p,k,l1=0,l2=0;
	for(i=1;i<=n;++i) p=read(),k=0,l[i]=p-k,r[i]=p+k;
	for(p=-2e9,i=1;i<=n;++i) if(l[i]>p) p=l[i],l1+=!(l1%2); else if(r[i]<p) p=r[i],l1+=l1%2;
	for(p=2e9,i=1;i<=n;++i)  if(r[i]<p) p=r[i],l2+=!(l2%2); else if(l[i]>p) p=l[i],l2+=l2%2;
	return !printf("%d",max(l1,l2));
}

华容道

Link
大力bfs。

#include <bits/stdc++.h>
using namespace std;
template<typename _Tp>inline void IN(_Tp&dig)
{
    char c;dig=0;
    while(c=getchar(),!isdigit(c));
    while(isdigit(c))dig=dig*10+c-'0',c=getchar();
}
int n,m,q,mp[35][35],ex,ey,sx,sy,tx,ty,tmp[35][35],dis[35][35][35][35][4],htab[10][35][35];
bool vis[35][35];
struct P{int h,w;}dirc[4]={{-1,0},{1,0},{0,-1},{0,1}};
struct ST
{
    int h,w,d,G,H;
    bool operator < (const ST another)const{return G+H>another.G+another.H;}
};
queue<P> que;
priority_queue<ST> pq;
inline int H(int h,int w){return abs(h-tx)+abs(w-ty);}
inline void bfs(int x1,int y1,int x2,int y2)
{
    memset(tmp,0,sizeof(tmp)),memset(vis,0,sizeof(vis));
    que.push((P){x1,y1}),vis[x1][y1]=1;
    for(int i=0;i<4;i++)dis[x1][y1][x2][y2][i]=-1;
    while(!que.empty())
    {
        P F=que.front(),nxt;que.pop();
        for(int i=0;i<4;i++)
        {
            if(F.h-dirc[i].h==x2&&F.w-dirc[i].w==y2)dis[x1][y1][x2][y2][i]=tmp[F.h][F.w];
            nxt.h=F.h+dirc[i].h,nxt.w=F.w+dirc[i].w;
            if(nxt.h<1||nxt.h>n||nxt.w<1||nxt.w>m)continue;
            if(vis[nxt.h][nxt.w]||!mp[nxt.h][nxt.w]||(nxt.h==x2&&nxt.w==y2))continue;
            tmp[nxt.h][nxt.w]=tmp[F.h][F.w]+1;
            que.push(nxt),vis[nxt.h][nxt.w]=1;
        }
    }
}
int main()
{
    IN(n),IN(m),IN(q);
    for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)IN(mp[i][j]);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)if(mp[i][j])
            for(int k=0;k<4;k++)if(mp[i+dirc[k].h][j+dirc[k].w])
                    bfs(i+dirc[k].h,j+dirc[k].w,i,j);
    while(q--)
    {
        memset(htab,127,sizeof(htab));
        while(!pq.empty())pq.pop();
        IN(ex),IN(ey),IN(sx),IN(sy),IN(tx),IN(ty),bfs(ex,ey,sx,sy);
        if(sx==tx&&sy==ty){printf("0
");goto end;}
        for(int i=0;i<4;i++)
            if(dis[ex][ey][sx][sy][i]!=-1)
            {
                ST nxt=(ST){sx,sy,i,dis[ex][ey][sx][sy][i],H(sx,sy)};
                pq.push(nxt),htab[nxt.d][nxt.h][nxt.w]=dis[ex][ey][sx][sy][i];
            }
        while(!pq.empty())
        {
            ST F=pq.top();pq.pop();
            if(F.h==tx&&F.w==ty){printf("%d
",F.G);goto end;}
            int eh=F.h+dirc[F.d].h,ew=F.w+dirc[F.d].w;
            for(int i=0;i<4;i++)
                if(dis[eh][ew][F.h][F.w][i]!=-1)
                {
                    ST nxt=(ST){F.h,F.w,i,F.G+dis[eh][ew][F.h][F.w][i],F.H};
                    if(htab[nxt.d][nxt.h][nxt.w]>F.G+dis[eh][ew][F.h][F.w][i])
                        pq.push(nxt),htab[nxt.d][nxt.h][nxt.w]=F.G+dis[eh][ew][F.h][F.w][i];
                }
            ST nxt=(ST){eh,ew,F.d^1,F.G+1,H(eh,ew)};
            if(htab[nxt.d][nxt.h][nxt.w]>F.G+1)
                pq.push(nxt),htab[nxt.d][nxt.h][nxt.w]=F.G+1;
        }
        printf("-1
");
        end:continue;
    }
    return 0;
}
原文地址:https://www.cnblogs.com/cjoierShiina-Mashiro/p/11869200.html