0x08 总结与练习

1:前面已经搞好了。

2:poj2965 这种开关问题一个点要么点一次要么不点,枚举所有点的方案实行即可

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;

char ss[10];
int main()
{
    int d=0,tp=0;
    for(int i=1;i<=4;i++)
    {
        scanf("%s",ss+1);
        for(int j=1;j<=4;j++,tp++)
            if(ss[j]==‘+‘)d+=(1<<tp);
    }
    int max_line=(1<<16)-1,ans=999999,zt;
    for(int i=0;i<=max_line;i++)
    {
        int k=d,sum=0;
        for(int j=0;j<=15;j++)
        {
            if((i&(1<<j))>0)
            {
                sum++;

                int h=j/4;
                for(int _=0;_<=3;_++)k^=(1<<(h*4+_));
                int l=j%4;
                for(int _=0;_<=12;_+=4)k^=(1<<(l+_));

                k^=(1<<(h*4+l));
            }
        }
        if(k==0)
        {
            if(ans>sum)
                ans=sum, zt=i;
        }
    }
    printf("%d\n",ans);
    int x=1,y=1;
    for(int j=0;j<=15;j++)
    {
        if((zt&(1<<j))>0)printf("%d %d\n",x,y);
        y++;if(y==5)y=1,x++;
    }
    return 0;
}

poj2965

3、4、10:手残码农题真心不想做,准备NOIP的时候再做吧

5:poj 3714 平面最近点对问题,分治解决,对于当前已有的最小值确定mid上下左右一个四边形的范围,合并区间时就判定这个四边形范围里面的点即可,闻说这个点数是不会超过8个的。具体实行是在确定了横坐标范围后,把这些点取出,判定时将其按纵坐标排序,一个个求值,这个复杂度是n(logn)^2,假如用归并排序顺便把纵坐标排序会少一个log,但是实际上并没有快多少。至于kdtree。。以后再说

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;

struct point{double x,y;int z;}a[210000],t[210000];
bool cmp(point p1,point p2){return p1.x<p2.x;}

int tt[210000];
bool cmp2(int n1,int n2){return a[n1].y<a[n2].y;}
double getdis(int n1,int n2)
{
    return sqrt( (double((a[n1].x-a[n2].x)*(a[n1].x-a[n2].x))) + (double((a[n1].y-a[n2].y)*(a[n1].y-a[n2].y))) );
}
double fenzi(int l,int r)
{
    if(l==r)return (double(1<<30));
    int mid=(l+r)/2;
    double mmin=min(fenzi(l,mid),fenzi(mid+1,r));

    int i=l,j=mid+1,p=l;
    while(i<=mid&&j<=r)
    {
        if(a[i].y<=a[j].y)t[p++]=a[i++];
        else               t[p++]=a[j++];
    }
    while(i<=mid)t[p++]=a[i++];
    while(j<=r)  t[p++]=a[j++];
    for(int i=l;i<=r;i++)a[i]=t[i];

    int len=0;tt[++len]=mid;
    for(int i=l;i<=r;i++)
        if(( double(abs(a[i].x-a[mid].x)) )<mmin)tt[++len]=i;

    for(int i=1;i<=len;i++)
        for(int j=i+1,clc=0;j<=len&&clc<=7;j++,clc++)
                if(a[tt[i]].z!=a[tt[j]].z)
                    mmin=min(mmin,getdis(tt[i],tt[j]));
    return mmin;
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
            scanf("%lf%lf",&a[i].x,&a[i].y), a[i].z=0;
        for(int i=n+1;i<=n*2;i++)
            scanf("%lf%lf",&a[i].x,&a[i].y), a[i].z=1;
        sort(a+1,a+2*n+1,cmp);

        printf("%.3lf\n",fenzi(1,2*n));
    }
    return 0;
}

poj3714

6:bzoj1271 这道是好题啊!突破口一定是在只有一个是奇数这个条件里面的,那么就是奇偶性的不同,这个时候并没有想到前缀和。知道这个以后就二分答案,看看前缀和是奇数还是偶数就行了。

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long LL;

int n;
struct node
{
    LL l,r,d;
}a[210000];
bool check(LL tp)
{
    LL sum=0;
    for(int i=1;i<=n;i++)
        if(a[i].l<=tp)sum+=(min(a[i].r,tp)-a[i].l)/a[i].d+1;
    return (sum%2==1);
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
            scanf("%lld%lld%lld",&a[i].l,&a[i].r,&a[i].d);

        LL l=1,r=2147483647,ans=-1;
        while(l<=r)
        {
            LL mid=(l+r)/2,u;
            if(check(mid)==true)
            {
                r=mid-1;
                ans=mid;
            }
            else l=mid+1;
        }
        if(ans==-1)printf("Poor QIN Teng:(\n");
        else
        {
            LL c=0;
            for(int i=1;i<=n;i++)
                if(a[i].l<=ans&&ans<=a[i].r&&(ans-a[i].l)%a[i].d==0)c++;
            printf("%lld %lld\n",ans,c);
        }
    }
    return 0;
}

bzoj1271

7:poj3179 这题明显就得写个二维前缀和嘛。。相应的就离散化一下。二分答案,然后两个for一个枚举行一个枚举列的后界,前界尽量往前,这个while往前走就好。

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;

int n,C;
struct node{int x,y;}a[510];
int lsxlen,lsylen,lsx[510],lsy[510];
void LSH()
{
    lsxlen=0;
    for(int i=1;i<=n;i++)lsx[++lsxlen]=a[i].x;
    sort(lsx+1,lsx+lsxlen+1);
    lsxlen=unique(lsx+1,lsx+lsxlen+1)-lsx-1;
    for(int i=1;i<=n;i++)
         a[i].x=lower_bound(lsx+1,lsx+lsxlen+1,a[i].x)-lsx;

    lsylen=0;
    for(int i=1;i<=n;i++)lsy[++lsylen]=a[i].y;
    sort(lsy+1,lsy+lsylen+1);
    lsylen=unique(lsy+1,lsy+lsylen+1)-lsy-1;
    for(int i=1;i<=n;i++)
         a[i].y=lower_bound(lsy+1,lsy+lsylen+1,a[i].y)-lsy;
}
int sum[510][510];
int getsum(int x,int y,int u,int v)
{
    return sum[x][y]-sum[x][v-1]-sum[u-1][y]+sum[u-1][v-1];
}
bool check(int mid)
{
    int rl=1;
    for(int rr=1;rr<=lsxlen;rr++)
    {
        while(lsx[rr]-lsx[rl]>=mid)rl++;
        int cl=1;
        for(int cr=1;cr<=lsylen;cr++)
        {
            while(lsy[cr]-lsy[cl]>=mid)cl++;
            if(getsum(rr,cr,rl,cl)>=C)return true;
        }
    }
    return false;
}
int main()
{
    scanf("%d%d",&C,&n);
    for(int i=1;i<=n;i++)
        scanf("%d%d",&a[i].x,&a[i].y);
    LSH();

    memset(sum,0,sizeof(sum));
    for(int i=1;i<=n;i++)sum[a[i].x][a[i].y]++;
    for(int i=1;i<=lsxlen;i++)
        for(int j=1;j<=lsylen;j++)
            sum[i][j]+=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1];

    int l=1,r=10000,ans;
    while(l<=r)
    {
        int mid=(l+r)/2;
        if(check(mid)==true)
        {
            ans=mid;
            r=mid-1;
        }
        else l=mid+1;
    }
    printf("%d\n",ans);
    return 0;
}

poj3179

8:bzoj1465 bzoj1045: [HAOI2008] 糖果传递&&bzoj3293: [Cqoi2011]分金币

9:明显x、y分开做,y就是中位数,x的话我一开始也是想要从中位数左右延伸,但是fail掉了。。正确的做法是设排完序以后,起点是a,那么我们就是要求的sum=Σabs(a-(x[i]-i))。a就是(x[i]-i)这东西的中位数。

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long LL;

LL a[11000],b[11000];
LL myabs(LL x){return x<0?-x:x;}
int main()
{
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%lld%lld",&a[i],&b[i]);
    sort(a+1,a+n+1);
    sort(b+1,b+n+1);
    for(int i=1;i<=n;i++)a[i]-=i;
    sort(a+1,a+n+1);

    LL sum=0;
    for(int i=1;i<=n;i++)
        sum+=myabs(a[i]-a[(n+1)/2]);
    for(int i=1;i<=n;i++)
        sum+=myabs(b[i]-b[(n+1)/2]);
    printf("%lld\n",sum);
    return 0;
}

poj1723

11:poj1050这题暴力二维前缀和n^4可A。。。。但是我还是正直的写个个n^3,f[i][j][k]表示现在枚举到第i行,列的区间是j~k的最大值,那么就相当于每一种列的情况都做一次O(n)的一维最大子串。

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;

int a[110][110],f[110][110][110];
int main()
{
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            scanf("%d",&a[i][j]);

    int ans=-2147483647;
    memset(f,0,sizeof(f));
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            int sum=0;
            for(int k=j;k<=n;k++)
            {
                sum+=a[i][k];
                f[i][j][k]=max(f[i-1][j][k]+sum,sum);
                ans=max(ans,f[i][j][k]);
            }
        }
    }
    printf("%d\n",ans);
    return 0;
}

poj1050

12:hdu4864 这题超级好题!!!!想了我超久,下午一个小时+晚上两个小时,看到那个价值的算法,肯定觉得会有问题对吧,我发现其实这个价值根本没用,因为价值的大小是按照耗时,耗时相等按照等级排的。思考的时候我类比一下贪心的第1题,那题是一个权,两个限制,现在是两个权,两个限制,不管怎样肯定是先排序,然后在此基础上卡另外一个限制贪心,我写的时候是让机器去找任务,这里就出问题了!不管按照什么排序,怎样的贪心法都会被反例掉,因为在这题里面,机器是为任务服务的,所以应该是任务去找机器,排序过后权值由大到小,一个个找完以后,x区间是单调延伸,前面的机器必然满足x比往后枚举的任务的x大,相当于问题只在于y,那么只需要贪心选择全部中尽量小的即可。再来分析一下正确性,当前任务占用机器,必然比后面的任务占用的机器要多,对于机器被占用,可以视作对答案的贡献均为1,所以可以心安理得的占用机器。对于机器而言,假如不影响当前任务影响后面,那一个替代他的机器一定比他还要优秀,它能影响了当前,肯定在先前也可以影响那个后一种情况中被前一个机器影响的任务。

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<set>
using namespace std;

struct node
{
    int x,y;
}a[110000],b[110000];
bool cmp(node n1,node n2)
{
    if(n1.x==n2.x)return n1.y>n2.y;
    return n1.x>n2.x;
}
multiset<int>s;
multiset<int>::iterator o;

int main()
{
    int n,m;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        for(int i=1;i<=n;i++)scanf("%d%d",&a[i].x,&a[i].y);
        for(int i=1;i<=m;i++)scanf("%d%d",&b[i].x,&b[i].y);
        sort(a+1,a+n+1,cmp);sort(b+1,b+m+1,cmp);

        s.clear();
        int ans=0,tp=1;long long val=0;
        for(int i=1;i<=m;i++)
        {
            while(tp<=n&&a[tp].x>=b[i].x)s.insert(a[tp].y),tp++;
            if(!s.empty())
            {
                if(*--s.end()>=b[i].y)
                {
                    int k=*s.lower_bound(b[i].y);
                    int c=s.count(k);s.erase(k);
                    for(int j=1;j<c;j++)s.insert(k);

                //    for(o=s.begin();o!=s.end();o++)printf("%d\n",*o);
                    ans++;val+=b[i].x*500+2*b[i].y;
                }
            }
        }
        printf("%d %lld\n",ans,val);
    }
    return 0;
}

hdu4864 (因为y的范围只有100所以可以暴力枚举,我没想就搞了个set,跑得还比暴力慢-_-!)

原文地址:https://www.cnblogs.com/AKCqhzdy/p/9245508.html

时间: 2024-08-30 04:30:19

0x08 总结与练习的相关文章

读取bq26500电池电量 Driver

bq26500是用于锂离子电池.锂聚合物电池充电.放电控制和监控的集成电路芯片.利用它能够准确提供电池充电.放电.电池温度.充放电电压.电池电量等相关数据.不须要外接微处理器參与电池充电.放电等相关数据的计算. 本文简单的读取了电池的电量百分比和电压.如要读取其它參数依照datasheet给出的寄存器一一读取就可以. 连接示意图: 引脚pack+ 和 pack-分别连接正极和负极用来冲放电,HDQ是数据交互引脚,用来读取电池的參数,一般用一个gpio连接就能够. 时序图: 看图可知.逻辑1和0并

在浏览器右键添加自定义菜单

在浏览器右键添加自定义菜单 Afly | 2006-11-8 其实就是类似当安装完 Flashget 后 Internet Explorer 的右键多了"使用网际快车下载"的选项一样,现在我们的需求是:当我们在图片右键时出现"复制图像地址"的选项. 其实很简单,先把下列代码存为 abc.reg 并导入: Windows Registry Editor Version 5.00 [HKEY_CURRENT_USER\Software\Microsoft\Interne

Linux下串口编制【转】

串行口是计算机一种常用的接口,具有连接线少,通讯简单,得到广泛的使用.常用的串口是RS-232-C接口(又称EIA RS-232-C)它是在1970年由美国电子工业协会(EIA)联合贝尔系统.调制解调器厂家及计算机终端生产厂家共同制定的用于串行通讯的标准.串口通讯指的是计算机依次以位(bit)为单位来传送数据,串行通讯使用的范围很广,在嵌入式系统开发过程中串口通讯也经常用到通讯方式之一. Linux对所有设备的访问是通过设备文件来进行的,串口也是这样,为了访问串口,只需打开其设备文件即可操作串口

浅谈libevent的使用--事件和数据缓冲

首先在学习libevent库的使用前,我们还要从基本的了解开始,已经熟悉了epoll以及reactor,然后从event_base学习,依次学习事件event.数据缓冲Bufferevent和数据封装evBuffer等,再结合具体的几个实例来了解libevent库的一些基本使用,有助于我们理解它的一些内部实现(由于之前我已经写过一篇epoll反应堆模型的,所以这里就不再介绍,直接从event_base开始介绍). libevent下载与安装: 在官网上找到 libevent-2.0.22-sta

[C语言]Base64编码解码

Base64编码解码 一,Base64编码原理 Base64编码的字符数组如下所示 : ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/ 字符串转Base64编码:取3字节的字符串转换为四字节的字符串,依次往后转换.得到Base64编码字符串.具体原理如下: 1,如果需要编码的原串字节数刚好为3的倍数,那么转换规则如下: 以中文字符'严'为例,'严'字的UTF-8编码为:0xE4B8A5 = 11100100  10

第三部分:S5PV210_时钟部分_1

时钟部分 (1)时钟域 S5PV210一共有三个时钟域:MSYS,DSYS,PSYS MSYS:(main system)主时钟域,包括CPU,DDR内存条,IROM和IRAM等 DSYS:(display system)显示时钟域,就是一般的和视频有关的就在这个时钟域中,如HDMI,TVENC... PSYS:(peripheral system)外围时钟域,就是GPIO接口,I2C接口,UART接口等这些外围设备就在这个时钟域上. 每个时钟域通过一条BRG(异步总线的桥梁)连接在一起. (2

msp头文件中文

MSP430寄存器中文注释---P1/2口(带中断功能) /************************************************************ * DIGITAL I/O Port1/2 寄存器定义 有中断功能 ************************************************************/ #define P1IN_               0x0020  /* P1 输入寄存器 */ const sfrb P

linux下,pipe的容量的讨论与查看

1.pipe的容量 2.6标准版本的linux内核,pipe缓冲区是64KB,尽管命令ulimit -a看到管道大小8块,缓冲区的大小不是4 k,因为内核动态分配最大16"缓冲条目",乘64 k.这些限制是硬编码的 2.如何查看自己pc上的pipe多大 1)通过ulimit -a查看到 pipe size 一次原子写入为:512Bytes*8=4096Bytes 查看缓冲条目个数:cat /usr/src/kernels/3.10.0-327.el7.x86_64/include/li

基于tiny4412的Linux内核移植 -- MMA7660驱动移植(九-2)

作者信息 作者: 彭东林 邮箱:[email protected] QQ:405728433 平台简介 开发板:tiny4412ADK + S700 + 4GB Flash 要移植的内核版本:Linux-4.4.0 (支持device tree) u-boot版本:友善之臂自带的 U-Boot 2010.12 (为支持uImage启动,做了少许改动) busybox版本:busybox 1.25 交叉编译工具链: arm-none-linux-gnueabi-gcc (gcc version 4