zoukankan      html  css  js  c++  java
  • The 2019 ICPC Asia Shanghai Regional Contest 补题

      重现赛过了三道题,我做出来了F题,其他题面都看了看没想到思路~

      挨个看题意看到了F,题意不就n个点的树,每个点有初始点权,需要维护m次操作:操作1:u到v的路径上的点权变成w。2:u到v的路径上的点权加w。3:u到v的路径上的点权乘w。4:求u到v的路径上的点权立方和。树上路径我会lca和树剖,要做到这样程度的修改用树剖+线段树比较合适。那么问题变成了维护区间立方和。我之前见过维护区间平方和的题,非常厉害,只需要维护区间和与区间平方和,每次pushdown的时候手推一下式子即可。我把三次方的式子(x+a)^3展开之后发现也很可写。那就开始码呗,想当年我可是连主席树都会写的人。码了半年才码出来,边的结构体还开小了,越界了好多发。

      A数多米诺骨牌的数量。RiCi太大了但是我会离散化。一个n^2的做法是预处理出每个点向右向下延伸的最长长度,然后先枚举点再枚举骨牌的大小,O(1)的判断能否组成。写着写着发现O(1)查询有点难搞,最后用了map多了个log(捂脸),不出意外的在第一组数据T飞了。

    #include<bits/stdc++.h> 
    using namespace std;
    const int N=5000010;
    int n;
    struct node
    {
        int x,y;
        friend bool operator < (node a,node b)
        {
            return a.x==b.x?a.y<b.y:a.x<b.x;
        }
    }o[N];
    map<node,int>maxx,maxy;
    bool cmpx(node a,node b)
    {
        return a.x==b.x?a.y<b.y:a.x<b.x;
    }
    bool cmpy(node a,node b)
    {
        return a.y==b.y?a.x<b.x:a.y<b.y;
    }
    int main()
    {
        int T,k,n;scanf("%d",&T);
        for(k=1;k<=T;k++)
        {
            scanf("%d",&n);
            for(int i=1;i<=n;i++)
                scanf("%d%d",&o[i].x,&o[i].y);
            maxx.clear();
            maxy.clear();
            sort(o+1,o+1+n,cmpx);
            for(int i=n;i;i--)
                if(o[i].x==o[i+1].x&&o[i].y==o[i+1].y-1)
                    maxy[node{o[i].x,o[i].y}]=maxy[node{o[i+1].x,o[i+1].y}]+1;
                else
                    maxy[node{o[i].x,o[i].y}]=1;
            sort(o+1,o+1+n,cmpy);
            for(int i=n;i;i--)
                if(o[i].y==o[i+1].y&&o[i].x==o[i+1].x-1)
                    maxx[node{o[i].x,o[i].y}]=maxx[node{o[i+1].x,o[i+1].y}]+1;
                else
                    maxx[node{o[i].x,o[i].y}]=1;
            int ans=0;
            for(int i=1;i<=n;i++)//1*2 
            {
                int a=maxx[node{o[i].x,o[i].y}],b=maxy[node{o[i].x,o[i].y}];
                for(int xx=1,yy=2;xx<=a&&yy<=b;xx++,yy+=2)
                    if(maxy[node{o[i].x+xx-1,o[i].y}]>=yy&&maxx[node{o[i].x,o[i].y+yy-1}]>=xx)
                        ans++;
                for(int xx=2,yy=1;xx<=a&&yy<=b;xx+=2,yy++)
                    if(maxy[node{o[i].x+xx-1,o[i].y}]>=yy&&maxx[node{o[i].x,o[i].y+yy-1}]>=xx)
                        ans++;
            }
            printf("Case #%d: %d
    ",k,ans); 
            
        }
    }
    A题Tn^2logn复杂度起飞代码

       写完了O(1)查询的代码,竟然A掉了?

    #include<bits/stdc++.h> 
    using namespace std;
    const int N=5000010;
    int n;
    struct node
    {
        int x,y,i
    }o[N];
    int maxx[N],maxy[N],xi[N],ix[N],yi[N],iy[N];
    bool cmpx(node a,node b)
    {
        return a.x==b.x?a.y<b.y:a.x<b.x;
    }
    bool cmpy(node a,node b)
    {
        return a.y==b.y?a.x<b.x:a.y<b.y;
    }
    bool cmpi(node a,node b)
    {
        return a.i<b.i;
    }
    int main()
    {
        int T,k,n;scanf("%d",&T);
        for(k=1;k<=T;k++)
        {
            scanf("%d",&n);
            for(int i=1;i<=n;i++)
                scanf("%d%d",&o[i].x,&o[i].y),o[i].i=i;
            o[n+1].x=0;
            o[n+1].y=0;
            o[n+1].i=0;
            sort(o+1,o+1+n,cmpx);
            for(int i=n;i;i--)
            {
                xi[i]=o[i].i;
                ix[o[i].i]=i;
                if(o[i].x==o[i+1].x&&o[i].y==o[i+1].y-1)
                    maxy[o[i].i]=maxy[o[i+1].i]+1;
                else
                    maxy[o[i].i]=1;
            }
            sort(o+1,o+1+n,cmpy);
            for(int i=n;i;i--)
            {
                yi[i]=o[i].i;
                iy[o[i].i]=i;
                if(o[i].y==o[i+1].y&&o[i].x==o[i+1].x-1)
                    maxx[o[i].i]=maxx[o[i+1].i]+1;
                else
                    maxx[o[i].i]=1;
            }
            sort(o+1,o+1+n,cmpi);
            int ans=0;
            for(int i=1;i<=n;i++)//1*2 
            {
                int a=maxx[i],b=maxy[i];
                for(int xx=1,yy=2;xx<=a&&yy<=b;xx++,yy+=2)
                    if(maxy[yi[iy[i]+xx-1]]>=yy&&maxx[xi[ix[i]+yy-1]]>=xx)
                        ans++;
                for(int xx=2,yy=1;xx<=a&&yy<=b;xx+=2,yy++)
                    if(maxy[yi[iy[i]+xx-1]]>=yy&&maxx[xi[ix[i]+yy-1]]>=xx)
                        ans++;
            }
            printf("Case #%d: %d
    ",k,ans); 
            
        }
    }
    总之就各种映射

       B题队友A掉了,看了题意,好想好写。问的是一堆字符串有没有是别人的前缀的。考虑读进来,sort之后用map维护即可。

    #include<bits/stdc++.h>
    using namespace std;
    map<string,int>mp;
    string s[10010],t;
    int len,n,T,i;
    int main()
    {
        cin>>T;
        for(int k=1;k<=T;k++)
        {
            cin>>n;
            mp.clear();
            for(i=1;i<=n;i++)
                cin>>s[i];
            sort(s+1,s+1+n);
            for(i=1;i<=n;i++)
            {
                len=s[i].length();
                t.clear();
                for(int j=0;j<len;j++)
                {
                    t+=s[i][j];
                    if(mp[t])
                    {
                        j=len+2;
                        i=n+1;
                        break;
                    }
                }
                mp[s[i]]=1;
            }
            printf("Case #%d: ",k);
            if(i==n+2)
                printf("No
    ");
            else
                printf("Yes
    ");
        }
    }
    B

       C就是在一个N*M矩形内左下角和右上角不能走,同时给定S个有财宝的点,K个有障碍的点不能走。问从左上角到右下角的方案数。我一看S才10,想到了容斥+二维DP。但是看到N、M<=100000就自闭了,DP不太行,容斥依然还行。注意到每一列的dp方程可以写矩阵乘法,但那是n^2的,不行。 想到了容斥之后问题就变成了M*N的矩阵左下角大小为a右上角大小为b的角落不能走的方案数,我和yxh想了很久也没想到,溜了溜了。

      E题是在一个有点权的矩形中规定起点和终点,从一个点走到另一个点时如果下一个点没走过就可以使答案+两个点权的乘积。

      

  • 相关阅读:
    vue单页面项目返回上一页无效,链接变化了,但是页面没有变化
    H5页面在iOS网页中的数字被识别为电话号码,字体颜色变黑色,且颜色不可改变
    vue-quill-editor 封装成组件;图片文件流上传;同一页面多个编辑器样式异常解决办法
    React 从零搭建项目 使用 create-react-app脚手架
    使用git pull文件时和本地文件冲突怎么办?
    webpack打包vue项目,资源路径如何从绝对路径改为相对路径?css中的图片资源如何修改配置?
    前端使用JS-SDK上传图片(文件)到七牛
    vue图片裁剪插件vue-cropper
    小程序图片裁剪组件
    微信小程序1rpx border ios真机显示不全问题
  • 原文地址:https://www.cnblogs.com/qywyt/p/14684745.html
Copyright © 2011-2022 走看看