国庆清北刷题冲刺班 Day7 下午

77 篇文章 0 订阅
75 篇文章 0 订阅

A 同花顺

题目原型:洛谷2652 同花顺
文件名 输入文件 输出文件 时间限制 空间限制
card.cpp/c/pas card.in card.out 1s 512MB
题目描述
所谓同花顺,就是指一些扑克牌,它们花色相同,并且数字连续。
现在我手里有 n 张扑克牌,但它们可能并不能凑成同花顺。我现在想知道,最
少更换其中的多少张牌,我能让这 n 张牌凑成一个同花顺?
输入格式
第一行一个整数 n,表示扑克牌的张数。
接下来 n 行,每行两个整数 a i 和 b i 。其中 a i 表示第 i 张牌的花色,b i 表示第
i 张牌的数字。
(注意: 这里的牌上的数字不像真实的扑克牌一样是 1 到 13, 具体见数据范围)
输出格式
一行一个整数,表示最少更换多少张牌可以达到目标。
样例输入 1
5
1 1
1 2
1 3
1 4
1 5
样例输出 1
0
样例输入 2
5
1 9
1 10
2 11
2 12
2 13
样例输出 2
2
数据范围
对于 30% 的数据,n ≤ 10。
对于 60% 的数据,n ≤ 10 5 ,1 ≤ a i ≤ 10 5 ,1 ≤ b i ≤ n。
对于 100% 的数据,n ≤ 10 5 ,1 ≤ a i ,b i ≤ 10 9 。
天宇哥哥不大地道啊,光出原题

#include<iostream>
#include<cstdio>
#include<algorithm>
#define MAXN 100005
using namespace std;
struct Data{
    int x,y;
    bool operator < (const Data &A) const {
        return A.x == x ? y < A.y : x < A.x;
    }
    bool operator == (const Data &A) const {
        return x == A.x && y == A.y;
    }
}a[MAXN];
inline void read(int &n){
    register char c=getchar(); bool temp=false;
    for(n=0;!isdigit (c);c=getchar()) if(c=='-') temp=true;
    for(;isdigit(c);n=n*10+c-'0',c=getchar());
    if(temp) n=-n;
}
inline void C_Max(int &a,int b){ if(b>a) a=b; }
int main (int argc, char *argv[]) {
    freopen("card.in","r",stdin);
    freopen("card.out","w",stdout);
    int n,M,r=0,s=0;
    read(n);
    register int i,j,k,l;
    for(i=1;i<=n;++i) read(a[i].x),read(a[i].y);
    sort(a+1,a+n+1);
    M=unique(a+1,a+n+1)-a-1;
    for(i=2,j=1;i<=M;++i)
        if (a[i].x!=a[i-1].x){
            for(r=0,k=j,l=j;k<=i-1;++k){
                for(;l<i-1&&a[l+1].y-a[k].y<n;++l);
                C_Max(r,l-k+1);
            }
            C_Max(s,r),j=i;
        }
    for(r=0,k=j,l=j;k<=i-1;++k){
        for(;l<i- 1&&a[l+1].y-a[k].y<n;++l);
        C_Max(r,l-k+1);
    }
    C_Max(s,r);
    cout<<n-s;
    fclose(stdin);fclose(stdout);
    return 0;
}

B 做实验

文件名 输入文件 输出文件 时间限制 空间限制
test.pas/c/cpp test.in test.out 1s 128MB
题目描述
有一天,你实验室的老板给你布置的这样一个实验。
首先他拿出了两个长度为 n 的数列 a 和 b,其中每个 a i 以二进制表示一个集
合。例如数字 5 = (101) 2 表示集合 {1,3}。第 i 次实验会准备一个小盒子,里面装
着集合 a i 所有非空子集的纸条。老板要求你从中摸出一张纸条,如果满足你摸出的
纸条是 a i 的子集而不是 a i−b i ,a i−b i +1 ,…,a i−1 任意一个的子集,那么你就要 *
反之,你就逃过一劫。
令你和老板都没有想到的是,你竟然每次都逃过一劫。在庆幸之余,为了知道
这件事发生的概率,你想要算出每次实验有多少纸条能使你 *
输入格式
第一行一个数字 n。
接下来 n 行,每行两个整数,分别表示 a i 和 b i 。
输出格式
n 行,每行一个数字,表示第 i 次实验能使你 * 的纸条数。
样例输入 1
3
7 0
15 1
3 1
样例输出 1
7
8
0
数据范围
对于 30% 的数据,n,a i ,b i ≤ 100
对于 70% 的数据,n,a i ,b i ≤ 60000
对于 100% 的数据,n,a i ,b i ≤ 10 5
保证所有的 a i 不重复,b i < i

这个题也是原题,栋栋又搜到题解了,居然没给我代码,导致我没拿奖品。。。

枚举子集、记录前一次出现的位置

//就这样枚举子集
for(int i=s;i;i=(i-1)&s)
#include<iostream>
#include<cstdio>
using namespace std;
int f[100010];
int n,a,b,Ans;
int main(){
    freopen("test.in","r",stdin);
    freopen("test.out","w",stdout);
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%d%d",&a,&b);
        Ans = 0;
        for(int j=a; j; j=(j-1)&a){
            if(f[j]<i-b) Ans++;
            f[j] = i;
        }
        printf("%d\n",Ans);
    }
    fclose(stdin);fclose(stdout);
    return 0;
}

C 拯救世界

题目又原型:洛谷 P3627 [APIO2009]抢掠计划
文件名 输入文件 输出文件 时间限制 空间限制
save.cpp/c/pas save.in save.out 1s 512MB
题目描述
C 城所有的道路都是单向的。不同道路之间有路口,每个路口都有一个大楼。
有一天, 城市里的所有大楼因为不明原因, 突然着火了。 作为超人的你要去拯救
这些大楼。初始的时候你在 S 号楼,最后你必须到达某个有补给站的大楼,你可以
沿着单向道路行驶。你可以经过某条道路或者某个大楼若干次,经过一个大楼你就
可以消灭一个大楼的大火。每个大楼都有一个重要程度,最后这个任务的评价分数
就是你经过的所有大楼的重要度之和(若重复经过某个大楼多次,则不重复算分) 。
你是一个聪明的超人,你想知道,通过合理的规划路线,你这次任务能得到的
最高得分是多少。
注意,该城市的道路可能有重边或自环。
输入格式
第一行包括两个整数 n,m,n 表示路口的个数(即大楼的个数) ,m 表示道路
的条数。
接下来 m 行,每行两个整数 x,y,表示 x 到 y 之间有一条单向道路。
接下来 n 行,每行一个整数,按顺序表示每个大楼的重要度。
接下来一行包含两个整数 S 和 P,S 是出发的路口(大楼)的编号,P 是有补
给站的大楼的数量。
接下来一行 P 个整数,表示有补给站的大楼的编号。
输出格式
输出一行一个整数,表示你得分的最大值。
样例输入 1
6 7
1 2
2 3
3 5
2 4
4 1
2 6
6 5
10
12
8
16
1
5
1 4
4 3 5 6
样例输出 1
47
数据范围
对于 1、2、3 测试点,N,M ≤ 300
对于 4、5、6、7、8、9、10 测试点,N,M ≤ 3000
对于 11、12、13、14、15 测试点,N,M ≤ 500000。每个大楼的重要度均为非
负数且不超过 4000。
输入数据保证你可以从起点沿着单向道路到达其中的至少一个有补给站的大
楼。
注意,输入数据中存在树和链的特殊情况

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<queue>
#include<algorithm>
#include<cstring>
using namespace std;
#define inf 0x7fffffff
#define LL long long
inline int read(int &x) {
    x=0;int f=1; char ch=getchar();
    while(ch>'9'||ch<'0'){ if(ch=='-')f=-1; ch=getchar(); }
    while(ch>='0'&&ch<='9'){ x=x*10+ch-'0'; ch=getchar(); } x*=f;
}
#define MAXN 500005
int n,m,S,p,tim,scc,top,cnt,Ans;
int head[MAXN],h[MAXN],f[MAXN];
int belong[MAXN],val[MAXN];
int c[MAXN],dfn[MAXN],low[MAXN],st[MAXN];
bool exist[MAXN];
struct data { int to,next; } e[MAXN<<1];
struct edge { int to,next; } ed[MAXN<<1];
void insert(int u,int val) {
    e[++cnt].to=val; e[cnt].next=head[u]; head[u]=cnt;
}
void ins(int u,int val) { ed[++cnt].to=val; ed[cnt].next=h[u]; h[u]=cnt; }
void Tarjan(int x) {
    int now=0;
    dfn[x]=low[x]= ++tim;
    st[++top]=x,exist[x]=1;
    for(int i=head[x]; i; i=e[i].next)
        if(!dfn[e[i].to]) {
            Tarjan(e[i].to);
            low[x]=min(low[x],low[e[i].to]);
        } else if(exist[e[i].to])low[x]=min(low[x],dfn[e[i].to]);
    if(low[x]==dfn[x]) {
        scc++;
        while(now!=x) {
            now=st[top--],belong[now]=scc;
            val[scc]+=c[now],exist[now]=0;
        }
    }
}
void RBuild() {
    cnt=0;
    for(int i=1; i<=n; i++)
        for(int j=head[i]; j; j=e[j].next)
            if(belong[i]!=belong[e[j].to])
                ins(belong[i],belong[e[j].to]);
}
void SPFA() {
    queue<int> q;
    q.push(belong[S]);
    exist[belong[S]]=1;
    f[belong[S]]=val[belong[S]];
    while(!q.empty()) {
        int now=q.front();exist[now]=false;q.pop();
        for(int i=h[now]; i; i=ed[i].next) {
            int v=ed[i].to;
            if(f[now]+val[v]>f[v]) {
                f[v]=f[now]+val[v];
                if(!exist[v]) exist[v]=1,q.push(v);
            }
        }
    }
}
int main(){
    freopen("save.in","r",stdin);
    freopen("save.out","w",stdout);
    read(n),read(m);
    for(int u,v,i=1; i<=m; i++) {
        read(u),read(v);
        insert(u,v);
    }
    for(int i=1; i<=n; i++) read(c[i]);
    for(int i=1; i<=n; i++) if(!dfn[i]) Tarjan(i);
    read(S),read(p);
    RBuild();
    SPFA();
    for(int x,i=1; i<=p; i++) 
        read(x),Ans=max(Ans,f[belong[x]]);
    printf("%d\n",Ans);
    fclose(stdin);fclose(stdout);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

七情六欲·

学生党不容易~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值