码迷,mamicode.com
首页 > 其他好文 > 详细

2017.10.2 QBXT 模拟赛

时间:2017-10-10 17:48:08      阅读:238      评论:0      收藏:0      [点我收藏+]

标签:技术   art   最大权值   倍增lca   target   bsp   out   efi   map   

题目链接

T1

我们所要求得是(a*b)|x 
也就是 使(a*b)的倍数小于x的个数之和 1<=x<=n 
我们可以 找一个c使得 (a*b*c)<=x  
由于我们所求的是一个三元有序对 即 (1,2,3) 与 (1,3,2) 是两种不同的方案数
所以 我们可以强制规定 a<b<c 
最坏的情况是(a*a*a)==x  所以我们就可以确定a的枚举范围 就是n开三次根号
同理 b最大枚举到 sqrt(n/a) 
n/(a*b) 即为 c 由于c>b>a 所以 我们枚举的c是大于b的 
c的实际个数为 n(a*b)-b 
每一个三元有序对一共有六种变换方式 最后*6加进ans 
还有一种情况是 a,b,c 中有两个数相等 例如 a==b>c 
我们只需要枚举 c==n/(a*a) 的个数 
每一个三元有序对 可以有三种变换  枚举的c的个数最后*3 加进ans 
最后一种情况就是 a==b==c 对ans的贡献为 1 简单判断一下就好了 
技术分享
#include<cstdio>
#include<cstdlib>
#include<cstring>

using namespace std;

long long n;

#ifdef unix
#define LL "%lld"
#else
#define LL "%I64d"
#endif

int main()
{
    freopen("a.in","r",stdin);
    freopen("a.out","w",stdout);

    scanf(LL,&n);
    long long ans=0,tmp=0;
    for (long long a=1,v;a*a<=(v=n/a);a++,ans++)
        for (long long b=a+1;b*b<=v;b++)
            tmp+=n/(a*b)-b;
    ans+=tmp*6;
    tmp=0;
    for (long long a=1,v;(v=a*a)<=n;a++)
    {
        tmp+=n/v;
        if (a*a<=n/a) tmp--;
    }
    ans+=tmp*3;
    printf(LL "\n",ans);

    return 0;
}
View Code

 

T2

 倍增LCA 巧妙地搞一搞 
 对于两个人 想要最大的权值 一定要先把对方给封锁 
 就是 让对方走过的点越少越好 
 所以 两个人 一定是先对着走 
 树上任意两个点之间的路径是唯一的 所以两个人碰面的点 也是一定的 
 即为 两个人之间点数的中位数 
 这个点用LCA 求出 
 求出之后 这个点还可能连着多条边 
 对于先手会先选一颗权值最大的子树 先走一条边
 后手会选次大的子树 走一条边
 两者退回继续选取要走的子树 
 直到走不动了 
 最后ans再加上已经占领的子树的权值 即为最大权值 
技术分享
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>

using namespace std;

const int maxn=100010;

int n,m,en,z[maxn*3],f[maxn][20],q[maxn],depth[maxn],sum[maxn*3][2],fd[maxn],start[maxn],end[maxn],value[maxn];

struct edge
{
    int e,d;
    edge *next;
}*v[maxn],ed[maxn<<1];

void add_edge(int s,int e,int d)
{
    en++;
    ed[en].next=v[s];v[s]=ed+en;v[s]->e=e;v[s]->d=d;
}

int get(int p,int d)
{
    if (d==-1) return p;
    int x=0;
    while (d)
    {
        if (d&1) p=f[p][x];
        d>>=1;
        x++;
    }
    return p;
}

int get_lca(int p1,int p2)
{
    if (depth[p1]<depth[p2]) swap(p1,p2);
    p1=get(p1,depth[p1]-depth[p2]);
    int x=0;
    while (p1!=p2)
    {
        if (!x || f[p1][x]!=f[p2][x])
        {
            p1=f[p1][x];
            p2=f[p2][x];
            x++;
        }
        else x--;
    }
    return p1;
}

int calc(int p1,int p2)
{
    if (p1==f[p2][0]) return value[1]-value[p2];
    else return value[p1]+fd[p1];
}

int calcp(int p,int v)
{
    int l=start[p]-1,r=end[p];
    while (l+1!=r)
    {
        int m=(l+r)>>1;
        if (v>z[m]) l=m;
        else r=m;
    }
    return r;
}

int main()
{
    freopen("b.in","r",stdin);
    freopen("b.out","w",stdout);

    scanf("%d%d",&n,&m);
    int tot=0;
    for (int a=1;a<n;a++)
    {
        int s,e,d;
        scanf("%d%d%d",&s,&e,&d);
        tot+=d;
        add_edge(s,e,d);
        add_edge(e,s,d);
    }
    depth[1]=1;
    int front=1,tail=1;
    q[1]=1;
    for (;front<=tail;)
    {
        int now=q[front++];
        for (edge *e=v[now];e;e=e->next)
            if (!depth[e->e])
            {
                depth[e->e]=depth[now]+1;
                fd[e->e]=e->d;
                f[e->e][0]=now;
                int p=now,x=0;
                while (f[p][x])
                {
                    f[e->e][x+1]=f[p][x];
                    p=f[p][x];
                    x++;
                }
                q[++tail]=e->e;
            }
    }
    int cnt=0;
    for (int a=n;a>=1;a--)
    {
        int now=q[a];
        start[now]=cnt+1;
        for (edge *e=v[now];e;e=e->next)
            if (depth[e->e]==depth[now]+1)
            {
                z[++cnt]=value[e->e]+e->d;
                value[now]+=value[e->e]+e->d;
            }
        z[++cnt]=tot-value[now];
        end[now]=cnt;
        sort(z+start[now],z+end[now]+1);
        sum[end[now]][0]=z[end[now]];
        sum[end[now]][1]=0;
        for (int a=end[now]-1;a>=start[now];a--)
        {
            sum[a][0]=sum[a+1][0];
            sum[a][1]=sum[a+1][1];
            if ((a&1)==(end[now]&1)) sum[a][0]+=z[a];
            else sum[a][1]+=z[a];
        }
        cnt++;
    }
    for (int a=1;a<=m;a++)
    {
        int p1,p2;
        scanf("%d%d",&p1,&p2);
        int lca=get_lca(p1,p2);
        int dist=depth[p1]+depth[p2]-2*depth[lca];
        int delta=dist/2+(dist&1);
        int px,px1,px2;
        if (depth[p1]-depth[lca]<delta) px=get(p2,dist-delta);
        else px=get(p1,delta);
        if (depth[p1]-depth[lca]<delta-1) px1=get(p2,dist-delta+1);
        else px1=get(p1,delta-1);
        if (depth[p2]-depth[lca]<dist-delta-1) px2=get(p1,delta+1);
        else px2=get(p2,dist-delta-1);
        int ans=0;
        if (p1==px)
        {
            if (p2==px) ans=sum[start[px]][0];
            else
            {
                int v2=calc(px2,px);
                int p=calcp(px,v2);
                ans=sum[p+1][0]+sum[start[px]][1]-sum[p][1];
            }
        }
        else
        {
            if (p2==px)
            {
                int v1=calc(px1,px);
                int p=calcp(px,v1);
                ans=v1+sum[p+1][1]+sum[start[px]][0]-sum[p][0];
            }
            else
            {
                int v1=calc(px1,px);
                int pp1=calcp(px,v1);
                int v2=calc(px2,px);
                int pp2=calcp(px,v2);
                if (pp2==pp1) pp2++;
                if (pp1>pp2) swap(pp1,pp2);
                ans=v1+sum[pp2+1][dist&1]+sum[pp1+1][1-(dist&1)]-sum[pp2][1-(dist&1)]+sum[start[px]][dist&1]-sum[pp1][dist&1];
            }
        }
        printf("%d\n",ans);
    }

    return 0;
}
View Code

T3

怀疑人生的搜索加9维DP
技术分享
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>

using namespace std;

#define now pre[a][b][c][d][e][s1][s2][s3][s4]
#define dis(a,b,c,d) (abs(a-c)+abs(b-d))

const int INF=0x3f3f3f3f;

int A,B,C,D,E,num[10][10],value[10][10][10],delta[10][10][40],dp[31][6][6][6][6][2][2][2][2];

char s[500];

bool map[6][6][6][6];

int main()
{
    freopen("c.in","r",stdin);
    freopen("c.out","w",stdout);

    scanf("%d%d%d%d%d",&A,&B,&C,&D,&E);
    for (int a=0;a<6;a++)
    {
        scanf("%s",s);
        int p=0;
        for (int b=0;b<6;b++)
        {
            int px=p;
            while (s[px]!=])
                px++;
            p++;
            num[a][b]=s[p]-0;
            p++;
            p++;
            for (int c=1;c<=num[a][b];c++)
            {
                int v=0;
                while (s[p]>=0 && s[p]<=9)
                {
                    v=v*10+s[p]-0;
                    p++;
                }
                value[a][b][c]=v;
                p++;
            }
            p=px+1;
        }
    }
    int base=0;
    for (int a=0;a<6;a++)
        for (int b=0;b<6;b++)
            if (a>=2 && a<=3 && b>=2 && b<=3) ;
            else
            {
                sort(value[a][b]+1,value[a][b]+num[a][b]+1);
                for (int c=2;c<=num[a][b];c++)
                    if (value[a][b][c]-value[a][b][c-1]==1) base+=A;
                for (int c=2;c<=3;c++)
                    for (int d=2;d<=3;d++)
                    {
                        if (dis(a,b,c,d)==1)
                        {
                            for (int e=1;e<=num[a][b];e++)
                            {
                                delta[c][d][value[a][b][e]]+=B;
                                delta[c][d][value[a][b][e]-1]+=C;
                                delta[c][d][value[a][b][e]+1]+=C;
                            }
                        }
                        if (dis(a,b,c,d)==2)
                        {
                            for (int e=1;e<=num[a][b];e++)
                            {
                                delta[c][d][value[a][b][e]]+=D;
                                delta[c][d][value[a][b][e]-1]+=E;
                                delta[c][d][value[a][b][e]+1]+=E;
                            }
                        }
                    }
                for (int c=0;c<6;c++)
                    for (int d=0;d<6;d++)
                        if (dis(a,b,c,d)<=2 && (c!=a || d!=b) && !map[a][b][c][d])
                        {
                            map[a][b][c][d]=map[c][d][a][b]=true;
                            if (c>=2 && c<=3 && d>=2 && d<=3) ;
                            else
                            {
                                int dist=dis(a,b,c,d);
                                for (int e=1;e<=num[a][b];e++)
                                    for (int f=1;f<=num[c][d];f++)
                                    {
                                        if (abs(value[a][b][e]-value[c][d][f])==0)
                                        {
                                            if (dist==1) base+=B;
                                            else base+=D;
                                        }
                                        if (abs(value[a][b][e]-value[c][d][f])==1)
                                        {
                                            if (dist==1) base+=C;
                                            else base+=E;
                                        }
                                    }
                            }
                        }
            }
    memset(dp,0x3f,sizeof(dp));
    dp[0][0][0][0][0][0][0][0][0]=base;
    for (int a=0;a<30;a++)
        for (int b=0;b<=num[2][2];b++)
            for (int c=0;c<=num[2][3];c++)
                for (int d=0;d<=num[3][2];d++)
                    for (int e=0;e<=num[3][3];e++)
                        for (int s1=0;s1<=1;s1++)
                            for (int s2=0;s2<=1;s2++)
                                for (int s3=0;s3<=1;s3++)
                                    for (int s4=0;s4<=1;s4++)
                                        if (dp[a][b][c][d][e][s1][s2][s3][s4]!=INF)
                                        {
                                            int v=dp[a][b][c][d][e][s1][s2][s3][s4];
                                            for (int sx1=0;sx1<=(b!=num[2][2]);sx1++)
                                                for (int sx2=0;sx2<=(c!=num[2][3]);sx2++)
                                                    for (int sx3=0;sx3<=(d!=num[3][2]);sx3++)
                                                        for (int sx4=0;sx4<=(e!=num[3][3]);sx4++)
                                                        {
                                                            int wmt=0;
                                                            if (sx1) 
                                                            {
                                                                wmt+=delta[2][2][a+1];
                                                                if (s1) wmt+=A;
                                                                if (s2) wmt+=C;
                                                                if (s3) wmt+=C;
                                                                if (s4) wmt+=E;
                                                            }
                                                            if (sx2) 
                                                            {
                                                                wmt+=delta[2][3][a+1];
                                                                if (s1) wmt+=C;
                                                                if (s2) wmt+=A;
                                                                if (s3) wmt+=E;
                                                                if (s4) wmt+=C;
                                                            }
                                                            if (sx3) 
                                                            {
                                                                wmt+=delta[3][2][a+1];
                                                                if (s1) wmt+=C;
                                                                if (s2) wmt+=E;
                                                                if (s3) wmt+=A;
                                                                if (s4) wmt+=C;
                                                            }
                                                            if (sx4) 
                                                            {
                                                                wmt+=delta[3][3][a+1];
                                                                if (s1) wmt+=E;
                                                                if (s2) wmt+=C;
                                                                if (s3) wmt+=C;
                                                                if (s4) wmt+=A;
                                                            }
                                                            if (sx1 && sx2) wmt+=B;
                                                            if (sx1 && sx3) wmt+=B;
                                                            if (sx1 && sx4) wmt+=D;
                                                            if (sx2 && sx3) wmt+=D;
                                                            if (sx2 && sx4) wmt+=B;
                                                            if (sx3 && sx4) wmt+=B;
                                                            int &t=dp[a+1][b+sx1][c+sx2][d+sx3][e+sx4][sx1][sx2][sx3][sx4];
                                                            if (t>v+wmt) t=v+wmt;
                                                        }
                                        }
    int ans=INF;
    for (int a=0;a<=1;a++)
        for (int b=0;b<=1;b++)
            for (int c=0;c<=1;c++)
                for (int d=0;d<=1;d++)
                    ans=min(ans,dp[30][num[2][2]][num[2][3]][num[3][2]][num[3][3]][a][b][c][d]);
    printf("%d\n",ans);

    return 0;
}
View Code

 

2017.10.2 QBXT 模拟赛

标签:技术   art   最大权值   倍增lca   target   bsp   out   efi   map   

原文地址:http://www.cnblogs.com/ruojisun/p/7646737.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!