首页 > 其他分享 >9.29题目大赏

9.29题目大赏

时间:2022-10-05 19:01:22浏览次数:82  
标签:题目 no int 9.29 fa MAXN 大赏 return po

2022-9-29

前两道真的很水,然而我写挂了QAQ

T1

智力大冲浪

简单得不能再简单的贪心。先将每个游戏按扣钱为第一关键字降序,时刻为第二关键字升序排列。因为我们希望无法完成的游戏扣的钱更少。然后,从头到尾扫一遍,如果当前的游戏能被安排在它的最后时刻,就一定把它安排,这样对前面时间的影响才最少。如果不能,就再看该时刻前面的某一时刻有没有被安排。如果有就安排,没有的话这个游戏就只能被放弃,\(m\)就减去个它的代价。

代码

#include<bits/stdc++.h>
using namespace std;
int m,n,x,ok[510]={0};
struct game
{
	int date,po,num;
}games[510];
bool cmp(game a,game b)
{
	if(a.po!=b.po)return a.po>b.po;
	return a.date<b.date;
}
int main()
{
	scanf("%d%d",&m,&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&x);
		games[i].date=x;
		games[i].num=i;
	}
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&x);
		games[i].po=x;
	}
	sort(games+1,games+n+1,cmp);
	for(int i=1;i<=n;i++)
	{
		int flag=0;
		for(int j=games[i].date;j>=1;j--)
			if(ok[j]==0){ok[j]=1;flag=1;break;}
		if(flag==0)m-=games[i].po;
	}
	printf("%d",m);
    return 0;
}

T2

[SHOI2013]发微博

同样一道水题。

暴力去模拟的复杂度是\(O(nm)\)的,发现是区间操作,考虑用类似前缀和的思路去优化。

用两个数组\(shou[i]\)和\(fa[i]\)表示第\(i\)个人目前收到的消息和发出的消息。那么每遇到一个“! i”,就把\(i\)的\(fa++\);遇到一个“+ i j”,就把\(shou[i]-=fa[j]\),\(shou[j]-=fa[i]\)。为什么?因为在\(i\)、\(j\)建立联系之前他们所发的消息是不会被对方收到的,这里我们提前计算。每遇到一个“- i j”,就把\(shou[i]+=fa[j]\),\(shou[j]+=fa[i]\),即把当前的前缀和加上。这样我们就把一个“+”操作和与之对应的“-”操作处理了。

但这样会面临一个问题:一个“+”操作未必有对应的“-”操作,因为两个人加了好友之后可以一直不删。为了解决这个问题,我们可以倒着扫描(因为一个“-”操作一定有对应的“+”操作),同时上述操作反过来即可。

代码

#include<bits/stdc++.h>
#define MAXN 200010
#define MAXM 500010
using namespace std;
int n,m;
struct node
{
    char op;
    int a,b;
}no[MAXM];
int fa[MAXN],re[MAXN];
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++)
    {
        getchar();
        no[i].op=getchar();
        if(no[i].op=='!')scanf("%d",&no[i].a);
        else scanf("%d%d",&no[i].a,&no[i].b);
    }
    for(int i=m;i>=1;i--)
    {
        if(no[i].op=='!')
            fa[no[i].a]++;
        else if(no[i].op=='+')
        {
            re[no[i].b]+=fa[no[i].a];
            re[no[i].a]+=fa[no[i].b];

        }
        else if(no[i].op=='-')
        {
            re[no[i].b]-=fa[no[i].a];
            re[no[i].a]-=fa[no[i].b];
        }
    }
    for(int i=1;i<=n;i++)
        printf("%d ",re[i]);
    return 0;
}

T3

[SHOI2013]发牌

乍一看以为是约瑟夫问题,但\(R_i\)在变化,不好解决。观察题目后发现问题可以转换成每次把\(01\)序列的某个\(1\)变成\(0\),并往后跳\(R_i\)个\(1\)这两个操作。可以用树状数组处理一个前缀和,每次往后跳的时候二分查找后面第\(R_i\)个\(1\)的位置并跳过去。

代码

#include<bits/stdc++.h>
#define MAXN 700010
using namespace std;
int n,r[MAXN],p=1,nowm;
int a[MAXN];
int nxt[MAXN],last[MAXN];
struct tree
{
    int lowbit(int x)
    {
        return x&(-x);
    }
    void add(int num,int data)
    {
        for(int i=num;i<=MAXN-9;i+=lowbit(i))
        {
            a[i]+=data;
        }
    }
    int getsum(int num)
    {
        int ans=0;
        for(int i=num;i>0;i-=lowbit(i))
        {
            ans+=a[i];
        }
        return ans;
    }
}tre;
int read()
{
    int x=0,f=1;
    char c=getchar();
    while(c<'0'||c>'9')
    {
        if(c=='-')f=-1;
        c=getchar();
    }
    while(c>='0'&&c<='9')
    {
        x=(x<<1)+(x<<3)+(c^48);
        c=getchar();
    }
    return x*f;
}
bool check(int st,int ed,int step)
{
    return tre.getsum(ed)-tre.getsum(st)<step;
}
int get_nxtk(int l,int r,int step)//在l到r的区间中,距开头为step的点的位置
{
    while(l<r)
    {
        int mid=(l+r)>>1;
        if(tre.getsum(mid)>=step)r=mid;
        else l=mid+1;
    }
    return l;
}
int main()
{
    n=read();
    for(int i=1;i<=n;i++)
    {
        r[i]=read();
        tre.add(i,1);
        last[i]=i-1;
        nxt[i]=i+1;
        if(last[i]==0)last[i]=n;
        if(last[i]==n+1)last[i]=1;
    }
    int cnt=n;
    for(int i=1;i<=n;i++)
    {
        int step=r[i]%cnt+1;
        int cha=tre.getsum(n)-tre.getsum(p-1);
        if(cha<step)
        {
            p=get_nxtk(1,p-1,step-cha);
        }
        else
        {
            int pro=tre.getsum(p-1);
            p=get_nxtk(p,n,pro+step);
        }
        printf("%d\n",p);
        last[nxt[p]]=nxt[p];
        nxt[last[p]]=last[p];
        tre.add(p,-1);
        cnt--;
        p=nxt[p];
    }
    return 0;
}

标签:题目,no,int,9.29,fa,MAXN,大赏,return,po
From: https://www.cnblogs.com/huled/p/16743124.html

相关文章

  • LeetCode - 字符串类型题目
    剑指Offer05.替换空格请实现一个函数,把字符串 s 中的每个空格替换成"%20"。方法:双指针首先统计空格数量count,然后为原字符串数组扩展出2*count的空间,用来存......
  • 题目
    题目1.列举你所了解的计算机存储设备类型?答:随机存储器RAMSRAM、DRAM(SDRAM、RDRAM、CDRAM等)只读存储器ROMMROM、PROM、EPROM、EEPROM2.一般代码存储在计算机的哪个设备中?......
  • Atcoder 题目选做
    ABC257G直接考虑\(\rmKMP\)的过程。\(\rmKMP\)可以帮助我们求出\(S\)的\(border\),并找到\(T\)中每一个位置能匹配上的\(S\)的最长前缀。那么我们就可以很......
  • 算法题目(2)
    题目1定义何为步骤和?比如680,680+68+6=754,680的步骤和叫754给定一个正数num,判断它是不是某个数的步骤和思路单调性。思路过程:首先想到如果直接从步骤和num倒推......
  • 前端-面试实战题目积累
    vue单向数据流的原理所有的prop使得其父子之间形成一个单向下行绑定,父组件--->子组件;父组件prop的更新会下流到子组件中,反过来不行;防止子组件意外变更父组件的状态,导致......
  • 题目集1~3的总结性Blog
    一、前言对于本次blog所涉及的题目,个人感觉主要是对于String类型的变量处理,以及对于面向过程所使用的类的用法有较高要求,难度也是逐渐递增,尤其是点线三角形更是如此,......
  • 题目集1~3的总结性Blog
    1.前言第一次作业难度相对较低,主要注重字符串的处理。第二次作业注重字符串的转换与匹配。第三次作业需要掌握正则表达式和代码复用,难度最高。2.设计与分析7-2串口字符......
  • PTA题目集阶段总结1
    PTA题目集阶段总结1 前沿概要 第一次写博客还是有点紧张的,毕竟我啥也不会,只能靠一点微薄的知识来支撑本篇文章的高度,在接下来的文章叙述中,如果你看出了些许(也有可能......
  • 题目集1~3的总结
    前言:前两次大作业题目主要是对java基本语法的考察,例如:基础类型的使用以及String类方法的使用。第三次大作业则开始进入到面向对象程序设计的范畴,考察了类的设计。总体......
  • 题目集1-3
    前言:三次题目集中前两次的题目较为容易,与C语言相差不大,用面向过程的思维基本可以解决,但第三次的题目需要用面向对象的思维,且目前对java的掌握不太够,所以感觉会有点困难,甚至......