前几天一直在忙小学期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但是能过的题
#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;
}
主要就是对问题的区间进行蜜汁分块,排序
最终降低复杂度
明儿再练一练