日更2019.7.3(2017广西邀请赛 HDU 6188 Duizi and Shunzi,covering)

前几天一直在忙小学期arduino和打比赛训练
现在补几题

题意:给你一堆牌,有两种组合方式,问最多能组合成多少个对子和顺子(同牌面的2张可以组成一个对子,连续牌面数字的3张可以组成一个顺子)

这个贪心策略就是
1、尽可能多的产生对子;
2、在线性判断中,假设现在的牌面数字为i的存在1张多余的组不成对子的,那么判断后面i+1的牌数是否为奇数,若是则继续,最后判断数字i+2的牌是否存在,若是则答案++;

为啥呢,证明如下
1、顺子代价>对子代价
2、若线性判断中,还存在数字 i 的牌,且后面i+1,i+2的牌存在,那么,判断i+1的牌数的奇偶性(1)、奇数,反正最后都要剩下,不如把i的牌利用一下,本来i和i+1的牌完全无法利用,而加上了i+2的牌就可以让答案++,所以可以最大化。(2)、偶数,若使用i+1的牌去凑顺子,那么本来可以完全组成对子的i+1牌被浪费了一张没法用,而且浪费了一张i+2的牌去凑得一个答案。
(例如数据
7
1 1 1 2 2 3 3答案为3)

#include<bits/stdc++.h>
using namespace std;
int a[1000006],b[1000005];
int main(){
    long long  n;
    while(~scanf("%lld",&n)){
        int p=0,ans=0,maxn=0;
        memset(b,0,sizeof(b));
        for(int i=0;i<n;i++){
            scanf("%d",&a[i]);
            b[a[i]]++;
            if(a[i]>maxn){
                maxn=a[i];
            }    
        }
        while(p<=maxn){
            if(!b[p]){
                p++;
                continue;
            }else {
                if(b[p]>=2){
                    ans+=b[p]/2;
                    b[p]%=2;
                }
                if(b[p]){
                    if(p+2<=maxn&&b[p+1]%2&&b[p+2]){
                        ans++;
                        b[p]--;
                        b[p+1]--;
                        b[p+2]--;
                    }else {
                        p++;
                    }
                }
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}

还有这个covering
推荐博客
https://blog.csdn.net/elbadaernu/article/details/77825979

接下来去看看杭电的好题目
并且看完挑战程序设计竞赛

算了先学上次的莫队
int read()
{
char x;
while((x = getchar()) > ‘9’ || x < ‘0’) ;
int u = x - ‘0’;
while((x = getchar()) <= ‘9’ && x >= ‘0’) u = (u << 3) + (u << 1) + x - ‘0’;
return u;
}
看到一个快速读取的神仙东西,这个位运算很灵性,仅限于正的
但是对于蒟蒻来说,这点时间算不了啥,总不可能卡这点时间叭
还是记下为妙
左移三位+左移一位=原数*10

好了,接下来莫队

一题用莫队会t但是能过的题

[SDOI2009]HH的项链


#include <bits/stdc++.h>

using namespace std;

int read()
{
    char x;
    while((x = getchar()) > '9' || x < '0') ;
    int u = x - '0';
    while((x = getchar()) <= '9' && x >= '0') u = (u << 3) + (u << 1) + x - '0';
    return u;
}
int buf[105];  
inline void write(int i) {  
    int p = 0;  
    if(i == 0) p++;  
    else while(i) {  
        buf[p++] = i % 10;  
        i /= 10;  
    }  
    for(int j = p-1; j >= 0; j--) putchar('0' + buf[j]);  
} 

#define il inline
#define re register

int block,ans=0,cnt[1000001];
int n,m,a[500010],Ans[500010];

struct node {
    int l,r,id;
}q[500010];

il bool cmp(node a,node b){
    return (a.l/block)^(b.l/block)?a.l<b.l:(((a.l/block)&1)?a.r<b.r:a.r>b.r);
}

il void add(int x){
    if(!cnt[a[x]])ans++;
    cnt[a[x]]++;
}

il void del(int x){
    cnt[a[x]]--;
    if(!cnt[a[x]])ans--;
}
int i;

int main(){
    n=read();
    for(i=1;i<=n;++i)a[i]=read();
    m=read();
    block=n/sqrt(m*2/3);
    for(i=1;i<=m;++i){
        q[i].l=read();
        q[i].r=read();
        q[i].id=i;
    }
    sort(q+1,q+m+1,cmp);
    int l=0,r=0;
    for(i=1;i<=m;++i){
        int ql=q[i].l,qr=q[i].r;
        while(l<ql)del(l++);
        while(l>ql)add(--l);
        while(r<qr)add(++r);
        while(r>qr)del(r--);
        Ans[q[i].id]=ans;
    }
    for(i=1;i<=m;++i)write(Ans[i]),printf("\n");
    return 0;
}

主要就是对问题的区间进行蜜汁分块,排序
最终降低复杂度

明儿再练一练

发布了61 篇原创文章 · 获赞 8 · 访问量 2478

猜你喜欢

转载自blog.csdn.net/weixin_43982216/article/details/94589871