NOIP2015 Revenge

辣鸡出题人,毁我比赛,颓我精神,耗我钱财,废我青春。

去年成绩惨不忍睹就不说了...好像是100+80+0+100+50+60。

大概列一下算法。

幻方:模拟

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
using namespace std;
int n,mat[50][50],px,py;
#define FO(s) {freopen(#s".in","r",stdin);freopen(#s".out","w",stdout);}
int main()
{
    cin>>n;
    memset(mat,0,sizeof(mat));
    px=1; py=(n+1)/2;
    mat[px][py]=1;
    //By zzq
    for(int i=2;i<=n*n;i++)
    {
        if(px==1&&py!=n)
        {
            px=n; ++py; mat[px][py]=i;
        }
        else if(py==n&&px!=1)
        {
            --px; py=1; mat[px][py]=i;
        }
        else if(px==1&&py==n)
        {
            ++px; mat[px][py]=i;
        }
        else
        {
            if(!mat[px-1][py+1])
            {
                --px; ++py; mat[px][py]=i;
            }
            else
            {
                ++px; mat[px][py]=i;
            }
        }
    }
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            printf("%d",mat[i][j]);
            if(j!=n) putchar(‘ ‘);
        }
        putchar(‘\n‘);
    }
}

信息传递:tarjan/鬼畜dfs(各种写丑写成平方的都有80)

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <stack>
using namespace std;
//tarjan!
int n,t[233333],low[233333],dfn[233333],cur=0,siz=2000000000;
bool instack[233333],ved[233333];
int ss[233333],sn=0;
void tarjan(int s)
{
    dfn[s]=low[s]=++cur; ss[++sn]=s;
    instack[s]=1; ved[s]=1;
    if(instack[t[s]]) low[s]=min(low[s],dfn[t[s]]);
    else if(!dfn[t[s]])
    {
        tarjan(t[s]);
        low[s]=min(low[s],low[t[s]]);
    }
    if(dfn[s]==low[s])
    {
        int cs=0;
        while(1)
        {
            ++cs;
            instack[ss[sn]]=0;
            int t=ss[sn--];
            if(t==s) break;
        }
        if(cs!=1) siz=min(siz,cs);
    }
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d",t+i);
    for(int i=1;i<=n;i++) if(!ved[i]) tarjan(i);
    printf("%d\n",siz);
}

斗地主:欧洲人

跳石头:二分

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <set>
using namespace std;
int D[233333],L,n,m;
bool ok(int x)
{
    int cp=0,del=0;
    for(int i=1;i<=n;i++)
    {
        if(D[i]-cp<x)
        {
            del++; continue;
        }
        cp=D[i];
    }
    if(L-cp<x) del++;
    return del<=m;
}
int main()
{
    scanf("%d%d%d",&L,&n,&m);
    for(int i=1;i<=n;i++) scanf("%d",D+i);
    int l=0,r=L;
    while(l<r)
    {
        int mid=(l+r+1)>>1;
        if(ok(mid)) l=mid; else r=mid-1;
    }
    printf("%d\n",l);
}

子串:dp

dp[k][i][j]表示最优情况下使用k个子串,用了A串第i个构成B串前j个的方案数。

dp[k][i][j]=qzh[k-1][i-1][j-1] (注意这个前缀和只有第二维)

如果a[i-1]=b[j-1],那么dp[k][i][j]+=dp[k][i-1][j-1]

考场上不知道是哪里抽风了顺手多记了一维= =

似乎要随便滚动一下

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
using namespace std;
int MOD=1000000007;
int n,m,w,qzh[2][1005][205],dp[2][1005][205];
char a[233333],b[233333];
int main()
{
    scanf("%d%d%d%s%s",&n,&m,&w,a+1,b+1);
    dp[0][0][0]=1;
    for(int i=0;i<=n;i++) qzh[0][i][0]=1;
    for(int k=1;k<=w;k++)
    {
        for(int i=0;i<=n;i++)
        {
            for(int j=0;j<=m;j++) qzh[k&1][i][j]=dp[k&1][i][j]=0;
        }
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
            {
                if(a[i]!=b[j]) continue;
                int&cp=dp[k&1][i][j];
                cp=qzh[(k-1)&1][i-1][j-1];
                if(a[i-1]==b[j-1]) cp=(cp+dp[k&1][i-1][j-1])%MOD;
            }
            for(int j=0;j<=m;j++) qzh[k&1][i][j]=(qzh[k&1][i-1][j]+dp[k&1][i][j])%MOD;
        }
    }
    printf("%d\n",qzh[w&1][n][m]);
}

运输计划:乱搞

考虑二分答案,对于每一个超过限制的,我们必然要在其上选择一条边删去,且该条边权>=实际值-二分值。

那么我们暴力路径+1,再暴力for一下每一条边即可。

什么?怎么+1?前缀和!

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
using namespace std;
#define SZ 666666
#define P 20
typedef pair<int,int> pii;
int n,m,fa[SZ],fv[SZ],vc[SZ],dep[SZ],fst[SZ],vb[SZ],nxt[SZ],M=0,qa[SZ],qb[SZ],ql[SZ],ea[SZ],eb[SZ],ec[SZ],reald[SZ];
void ad_de(int a,int b,int c) {++M; nxt[M]=fst[a]; fst[a]=M; vb[M]=b; vc[M]=c;}
int cc=0,app[SZ],bs[SZ],up[SZ][P],cx[SZ],c2=0;
pii pp[SZ],minn[SZ][P];
void dfs(int x)
{
    ++cc; app[x]=cc; pp[cc]=pii(dep[x],x); cx[++c2]=x;
    for(int e=fst[x];e;e=nxt[e])
    {
        int b=vb[e]; if(b==fa[x]) continue;
        fa[b]=x; fv[b]=fv[x]+vc[e]; dep[b]=dep[x]+1;
        dfs(b); pp[++cc]=pii(dep[x],x);
    }
}
void build()
{
    for(int i=1;i<=n;i++) up[i][0]=fa[i];
    for(int p=1;p<P;p++)
    {
        for(int i=1;i<=n;i++)
        {
            if(up[i][p-1]) up[i][p]=up[up[i][p-1]][p-1];
        }
    }
    for(int i=1;i<=cc;i++) minn[i][0]=pp[i];
    for(int i=1;i<=cc;i++)
    {
        int g=0;
        while((1<<g)<=i) ++g;
        bs[i]=g-1;
    }
    for(int p=1;p<P;p++)
    {
        for(int i=1;i<=cc;i++)
        {
            if(i+(1<<p)-1>cc) break;
            minn[i][p]=min(minn[i][p-1],minn[i+(1<<(p-1))][p-1]);
        }
    }
}
int jump(int x,int d)
{
    for(int i=P-1;i>=0;i--)
    {
        if(up[x][i]&&dep[up[x][i]]>=d) x=up[x][i];
    }
    return x;
}
int lca(int a,int b)
{
    a=app[a]; b=app[b];
    if(a>b) swap(a,b);
    int l2=bs[b-a+1];
    return min(minn[a][l2],minn[b-(1<<l2)+1][l2]).second;
}
int dis(int a,int b,int l)
{
    return fv[a]+fv[b]-fv[l]*2;
}
int pv[SZ],cv[SZ];
bool ok(int x)
{
    int cnt=0,need=0;
    for(int i=1;i<=n;i++) pv[i]=0;
    for(int i=1;i<=m;i++)
    {
        if(reald[i]<=x) continue;
        ++cnt; pv[ql[i]]-=2; pv[qa[i]]++; pv[qb[i]]++;
        need=max(need,reald[i]-x);
    }
    if(!cnt) return 1;
    for(int i=n;i>=1;i--) pv[fa[cx[i]]]+=pv[cx[i]];
    for(int i=1;i<n;i++)
    {
        if(ec[i]<need) continue;
        if(pv[eb[i]]!=cnt) continue;
        return 1;
    }
    return 0;
}
#define BUFSIZE 300000
namespace fib {char b[BUFSIZE]={},*f=b;}
#define gc ((*fib::f)?(*(fib::f++)):(fgets(fib::b,sizeof(fib::b),stdin)?(fib::f=fib::b,*(fib::f++)):-1))
int g_i()
{
    int tmp=0; bool fu=0; char s;
    while(s=gc,s!=‘-‘&&(s<‘0‘||s>‘9‘)) ;
    if(s==‘-‘) fu=1; else tmp=s-‘0‘;
    while(s=gc,s>=‘0‘&&s<=‘9‘) tmp=tmp*10+s-‘0‘;
    if(fu) return -tmp; else return tmp;
}
#define gi g_i()
namespace fob {char b[BUFSIZE]={},*f=b,*g=b+BUFSIZE-2;}
#define pob (fwrite(fob::b,sizeof(char),fob::f-fob::b,stdout),fob::f=fob::b,0)
#define pc(x) (*(fob::f++)=(x),(fob::f==fob::g)?pob:0)
struct foce {~foce() {pob; fflush(stdout);}} _foce;
namespace ib {char b[100];}
inline void pint(int x)
{
    if(x==0) {pc(48); return;}
    if(x<0) {pc(‘-‘); x=-x;}
    char *s=ib::b;
    while(x) *(++s)=x%10, x/=10;
    while(s!=ib::b) pc((*(s--))+48);
}
int main()
{
    n=gi,m=gi;
    for(int i=1;i<n;i++)
    {
        int a=gi, b=gi, c=gi;
        ea[i]=a; eb[i]=b; ec[i]=c;
        ad_de(a,b,c); ad_de(b,a,c);
    }
    for(int i=1;i<=m;i++) qa[i]=gi, qb[i]=gi;
    dfs(1); build();
    int l=0,r=0;
    for(int i=1;i<=m;i++) ql[i]=lca(qa[i],qb[i]), reald[i]=dis(qa[i],qb[i],ql[i]), r=max(r,reald[i]);
    for(int i=1;i<n;i++) if(dep[ea[i]]>dep[eb[i]]) swap(ea[i],eb[i]);
    while(l<r)
    {
        int mid=l+r>>1;
        if(ok(mid)) r=mid; else l=mid+1;
    }
    printf("%d\n",l);
}

然后我们只要兹磁O(1) lca就行了。可能需要卡常~(我卡了三发才过)

时间: 2024-10-12 12:50:19

NOIP2015 Revenge的相关文章

HDU 4099 Revenge of Fibonacci

Revenge of Fibonacci Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 204800/204800 K (Java/Others) Total Submission(s): 2027    Accepted Submission(s): 475 Problem Description The well-known Fibonacci sequence is defined as following: Here w

[NOIP2015] 跳石头

2107. [NOIP2015] 跳石头 ★   输入文件:2015stone.in   输出文件:2015stone.out   简单对比时间限制:1 s   内存限制:256 MB [题目描述] 这项比赛将在一条笔直的河道中进行,河道中分布着一些巨大岩石.组委会已经选 择好了两块岩石作为比赛起点和终点.在起点和终点之间,有 N 块岩石(不含起点和终 点的岩石).在比赛过程中,选手们将从起点出发,每一步跳向相邻的岩石,直至到达 终点. 为了提高比赛难度,组委会计划移走一些岩石,使得选手们在比赛

hdu 4787 GRE Words Revenge 在线AC自动机

hdu 4787 GRE Words Revenge Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 327680/327680 K (Java/Others)Total Submission(s): 2505    Accepted Submission(s): 614 Problem Description Now Coach Pang is preparing for the Graduate Record Examina

树链剖分-Hello!链剖-[NOIP2015]运输计划-[填坑]

This article is made by Jason-Cow.Welcome to reprint.But please post the writer's address. http://www.cnblogs.com/JasonCow/ [NOIP2015]运输计划    Hello!链剖.你好吗? 题意: 给出一棵n个节点的带权树,m对树上点对 现在允许删除一条边,(权值修改为0) 输出: 最小化的点对间最大距离 1.链剖 2.树上差分 3.二分 链剖我就不多说了,就是两dfs 注意

HDU3341 Lost&#39;s revenge(AC自动机+DP)

题目是给一个DNA重新排列使其包含最多的数论基因. 考虑到内存大概就只能这么表示状态: dp[i][A][C][G][T],表示包含各碱基个数为ACGT且当前后缀状态为自动机第i的结点的字符串最多的数论基因数 其中ACGT可以hash成一个整数(a*C*G*T+c*G*T+g*T+T),这样用二维数组就行了,而第二维最多也就11*11*11*11个. 接下来转移依然是我为人人型,我是丢进一个队列,用队列来更新状态的值. 这题果然挺卡常数的,只好手写队列,最后4500msAC,还是差点超时,代码也

Openjudge NOI题库 ch0111/10 河中跳房子|NOIP2015 day2 stone

这题同时也是NOIP2015 D2T1 跳石头 stone 原题. 总时间限制: 1000ms 内存限制: 65536kB 描述 每年奶牛们都要举办各种特殊版本的跳房子比赛,包括在河里从一个岩石跳到另一个岩石.这项激动人心的活动在一条长长的笔直河道中进行,在起点和离起点L远 (1 ≤ L≤ 1,000,000,000) 的终点处均有一个岩石.在起点和终点之间,有N (0 ≤ N ≤ 50,000) 个岩石,每个岩石与起点的距离分别为Di (0 < Di < L). 在比赛过程中,奶牛轮流从起点

Revenge of Fibonacci(杭电5018)

Revenge of Fibonacci Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 721    Accepted Submission(s): 332 Problem Description In mathematical terms, the sequence Fn of Fibonacci numbers is define

HDU 5087 Revenge of LIS II(次长上升子序列)

题意  求一个序列的所有上升子序列中第二长的那个的长度 简单的dp   d[i]表示以第i个数结尾的最长上升子序列的长度  c[i]表示到达d[i]的方法数  如序列1 1 2  d[3]=2,c[3]=2  因为选1 3位置和 2 3位置的都可以得到d[3]=2 递推过程很简单 d[i]=max{d[j]+1}其中a[i]>a[j]&&i>j 最后看d[1~n]中最大的数出现了几次  出现了不止一次就直接输出否则就减一输出咯 #include <cstdio> #

HDU 5019 Revenge of GCD

Revenge of GCD Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 430    Accepted Submission(s): 122 Problem Description In mathematics, the greatest common divisor (gcd), also known as the greate