9月30日比赛总结

这次王w的比赛,用的题曾在胜利一中出现过。

上午

开始比赛时,第一题是裸裸的树状数组。。。我逗比的忘了怎么写Orz。于是。。。于是果断开了第二题。

T2

赛马 horseracing
题目背景 Background
一天,瑶子在家刷题,刚点击完submit按钮,突然眼前一闪,睁开眼后瑶子发现自己竟然穿越到了唐朝(好烂俗的剧情-。-),瑶子发现自己正在参加驸马竞选(我靠,这也太扯了吧),本来有些惊恐的瑶子突然来了兴致!!他打算赢得比赛迎娶公主,从此幸福的生活在一起。所以请你帮助瑶子赢得比赛。
题目描述 Description
比赛项目是赛马。瑶子和对手各有n匹马,每匹马有各自的速度v[i]。因为瑶子太帅,所以他可以选择对手的任意一匹马与自己的马进行一场比赛。在每匹马只能进行一次比赛的前提下,请求出n场比赛后,瑶子最多能获胜多少局。
输入输出格式 Input/output
输入格式:
第一行一个整数n,表示双方拥有的马的总数。
第二行n个整数,第i个数表示瑶子的第i匹马的速度v1[i]。
第三行n个整数,第i个数表示对手的第i匹马的速度v2[i]。
输出格式:
仅一个整数,表示瑶子能获胜局数的最大值。
输入输出样例 Sample input/output
样例测试点#1
输入样例: 在线IDE
3
1 2 3
1 2 3
输出样例:
2
说明 description
对于100%的数据,0

#include<algorithm>
#include<cstdio>
#include<iostream>
#define ff(i) for(int i=1;i<=n;i++)                  //用了宏
using namespace std;
int v1[1000000+5],v2[1000000+5],n;
int main(){
    cin>>n;
    ff(i) scanf("%d",&v1[i]);                        //用cin保证超时
    ff(i) scanf("%d",&v2[i]);
    sort(v1+1,v1+n+1);
    sort(v2+1,v2+n+1);
    int j=1;
    ff(i)if(v1[i]>v2[j])j++;                       //就是从小往大的拍,直到v1走完,v2走过的就是解
    cout<<j-1;
    return 0;
}

还有那传说中的std,孰优孰劣很清楚。。。完全没必要cmp判断。
赛马的传说中的std
然后看了看,直接转到t6

T6

卖山竹 sale
题目描述 Description
萌萌哒小山猪得到了一条货物(山竹≈山猪)流通渠道,来买的顾客都想要最大的山竹(猪),顾客要求小山猪用最短的时间找出来,而山猪同时还要处理山竹(猪)的进货,所以想写个程序来帮着处理
输入输出格式 Input/output
输入格式:
每一行第一个数如果是1,那么后面跟着两个数W,num,表示有一个重量为W,编号为num的山竹(猪)进入仓库,如果是2,表示一个顾客来买,接着输出最大的山竹的编号,并删除该山竹(猪)
如果是0的话,表示输入结束
输出格式:
对于每一次询问,输出一行数字,表示最大的山竹(猪)的编号
如果缺货,就输出-1
输入输出样例 Sample input/output
样例测试点#1
输入样例: 在线IDE
1 29949 1
1 684612 5
1 654655 7
2
2
2
2
0
输出样例:
5
7
1
-1
样例测试点#2
输入样例: 在线IDE
2
1 9174 1
2
1 8923 2
2
2
0
输出样例:
-1
1
2
-1
说明 description
数据保证W不重复
设输入个数N
对于40%的数据,1≤N≤10000
对于80%的数据,1≤N≤100000
对于100%的数据,1≤N≤500000
重量均在10000000范围内。
//注意 山竹(猪)的编号≤2000000.
哦,赤裸裸的堆。Travis用的hash,SHM用的重载运算符+优先队列,都是直接AC。为什么我的struct却挂了40分呢?不懂,求神犇讲解。
如下,40分代码。。。据说将堆判断符号加上=就A了,,,可能会有相同的重量吧。。。

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
struct wangw{
    int num,w;
}a[500000+3];
int m=1;
void swap (int x,int y){
    int t=a[x].w;
    a[x].w=a[y].w;
    a[y].w=t;
    t=a[x].num;
    a[x].num=a[y].num;
    a[y].num=t;
}
void insert(int w,int num){
    a[m].w=w;
    a[m].num=num;
    int p=m++;
    while(p!=1){
        if(a[p].w>a[p>>1].w)swap(p,p>>1);
        else return;
        p>>=1;
    }
}
void www(){
    if(m==1){printf("-1\n");return ;}
    printf("%d\n",a[1].num);
    m--;
    a[1].num=a[m].num;
    a[1].w=a[m].w;
    int p=1,q=2;
    while(p<=(m<<1)){
        if(a[q].w<a[q+1].w&&q<m)q++;
        if(a[p].w<a[q].w)swap(p,q);else return;
        p=q;
        q<<=1;
    }
}
int main(){
    memset(a,0,sizeof(a));
    int n,d,num,w;
    while(scanf("%d",&d)==1){
        if(d==0)return 0;
        if(d==1){
            scanf("%d%d",&w,&num);
            insert(w,num);
        }
        else www();
    }
    return 0;
}

还有std的函数(主函数没复制下来)。。。
失败者如是说,如果位运算会更快

#include<cstdio>
#include<algorithm>
#include<iostream> using namespace std;
int heap[2000001],w[2000001],tot=0,o1,o2,o3; void heap_add(int x)
{
heap[++tot] = x;
for (int i = tot; i > 1; i /= 2)
{
if (w[heap[i]]<w[heap[i/2]]) break;
else swap(heap[i],heap[i/2]);
}
}
void update(int x)
{
if (x*2 > tot) return;
if (x*2 == tot)
{
if(w[heap[x]]<w[heap[2*x]])
{
swap(heap[x],heap[2*x]);
update(2*x);
return;
}
}
if (w[heap[2*x]]<w[heap[2*x+1]])
{
if(w[heap[x]]<w[heap[2*x+1]])
{
swap(heap[x],heap[2*x+1]);
update(2*x+1);
}
}
else
{
if(w[heap[x]]<w[heap[2*x]])
{
swap(heap[x],heap[2*x]);
update(2*x);
}
}
}
int get_top()
{
if (!tot) return -1; int k=heap[1]; heap[1]=heap[tot--]; update(1);
return k;
}

然后我就开始做T3

T3

宗教信仰 religion
题目描述 Description
在一片大陆上有许多个国家和许多个宗教。每一个国家在某一时刻仅有1个官方信仰的宗教。
这些宗教可能会互相兼并,合成一个宗教。某个国家也可能在某一时刻改信一个宗教。
现在给出宗教兼并和国家改宗的大事表,以及若干个询问,询问在当前时刻2个国家是否信仰一个宗教。
每个国家在开始时,都信仰着不同的宗教。
输入输出格式 Input/output
输入格式:
第一行 1 个整数 N 表示国家数量。
第二行 1 个整数 Q 表示一共有Q个大事及询问。
以下 Q 行 每行形式如下:
1 A B 表示 A 国所信仰的宗教与 B 国所信仰的宗教 合并为 1 个宗教;
2 A B 表示 A 国改为信仰 B 国所信仰的宗教;
3 A B 表示查询 A 国 和 B 国 现在是否信仰同一个宗教;
//如果 1 2 3信仰A宗教,4 5信仰B宗教,那么执行2 1 4 后,2 3国信仰A宗教,1 4 5国信
//仰B宗教
输出格式:
对于每一个 询问 输出 ‘Yes’ 或 ‘No’ 来回答询问,分别表示是同一个宗教或不是同一个宗教.
输入输出样例 Sample input/output
样例测试点#1
输入样例: 在线IDE
5
6
1 3 4
1 2 4
3 2 4
2 5 2
3 1 5
3 3 5
输出样例:
Yes
No
Yes
样例测试点#2
输入样例: 在线IDE
5
6
1 1 2
1 1 3
1 1 4
3 1 2
2 4 5
3 1 2
输出样例:
Yes
Yes
说明 description
对于50% 的数据 1≤n≤10000;1≤q≤10000;
对于100%的数据 1≤n≤1000000;1≤q≤1000000;
/*数据太大传不上来了= =
另外存在:
10% 的数据 所有 2 操作在 1 操作之后;
10% 的数据 所有 1 操作在 2 操作之后;
10% 的数据 1 操作的个数 ≤ 10 ;
10% 的数据 2 操作的个数 ≤ 10 ;
*/
很长的一道题Orz。但仔细理解起来还算可以。操作1、3就是并查集操作,2需要另加其他操作。。。没想出来,只有并查集交了上去。。。50分。。。没错,一共就两个测试点。。。
所以直接std

/***
半裸的并查集,操作 1 和操作 3 按照平常的并查集写即可.
但是对于 2 操作,由于只改变一个点而不改变所属集合,所以每个 2 操作需要新建一个点,指向新的 集合.
所以对于每一个国家,记 Pi 为当前表示当前第 i 个国家在并查集中的点是哪一个,1 操作合并两个 集合,2 操作建一个新点指向目标集合,并维护 Pi,3 操作为查询.***/
var n,i,j,k,opt,a,b,total,q:longint; f:array[0..10000000]of longint; now:array[0..1000000]of longint;
function find(x:longint):longint; begin
if x=f[x] then exit(x); f[x]:=find(f[x]); exit(f[x]);
end;
procedure union(x,y:longint); begin
f[find(now[x])]:=find(now[y]);
end;
procedure change(x,y:longint); begin
inc(total);f[total]:=find(now[y]);now[x]:=total;
end;
procedure query(x,y:longint); begin
if find(now[x])=find(now[y]) then writeln('Yes') else writeln('No');
end; begin
readln(n);
for i:=1 to n do begin
f[i]:=i;now[i]:=i;
end;
total:=n;
readln(q);
for i:=1 to q do begin
readln(opt,a,b);
if opt=1 then union(a,b); if opt=2 then change(a,b); if opt=3 then query(a,b);
end;
end.

为什么没有C++代码?!c党人很。。。
然后开始看第五题

T5

萌萌指数和 sum
题目背景 Background
当腹黑的指数遇上呆萌的模运算,(“▔□▔)/你懂得(“▔□▔)/
题目描述 Description
求1^b+2^b+3^b+……+a^b的和mod 10000的结果。
输入输出格式 Input/output
输入格式:
第一行一个整数T,表示一共有T组数据。
接下来T行,每行两个整数a,b。
输出格式:
一共T行。
每行仅一个整数表示结果。
输入输出样例 Sample input/output
样例测试点#1
输入样例: 在线IDE
1
2 3
输出样例:
9
说明 description
对于30%数据,T<=10, a,b<=1000
对于100%数据,T<=100, a,b<=1,000,000,000

超级快速幂。。。传送门——http://blog.csdn.net/marshalben/article/details/48832353
上午就这么结束了。。。

下午

下午的题目很。。。不说了,一个都没A

T4

Src运货 tran
题目描述 Description
Src是一名司机,负责在城市间运输货物。他想要沿着城市间最短的路径行驶,来用最短的时间到达目的地。
可不幸的是,在高速公路上时常有堵车现象发生。而堵车可能使得Src的一次行程变长。
Src会在每次开始行程前查询一次路况,会得到某条路已经堵塞的信息,他会根据这些信息作出是否需要多带一些金坷垃来作口粮。
即:如果这条路堵塞后会使得本次行程的最短路径变长,那么他需要多带一些口粮。
现在给出Src所知道的路况(某两个城市之间的高速公路堵塞(不可通行)了),以及这一次行程的起点和终点,请帮他判断他是否需要多带一些金坷垃在路上吃。

Src工作的地域是由 N 个点和 M 条双向通行的边构成的。
输入将给出 M 条边的 起点 , 终点 , 长度,
并给出 Q 个询问,包含 这一次行程的 起点 , 终点 , 可能会堵塞的路的起点与终点 。
//这里高速公路的堵塞是单向的,即只有和输入给出方向相同的路会不可通行
请回答他是否需要多带金坷垃(是:”Y”;否:”N”)。
//如果 S 到 T 的最短路有 N 条,道路堵塞仅堵塞了 K(K

#include<cstdio>
#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
int map[500+3][500+3],a[500+3];
int s,e,sl,tl;  int n,m,u,v,l;
queue<int>q;
int spfa(){
    for(int i=1;i<=n;i++)
    a[i]=1<<31-1;
    a[s]=0;
    q.push(s);
    while(!q.empty()){
        int i=q.front();
        for(int j=1;j<=n;j++){
            if(map[i][j]&&map[i][j]+a[i]<a[j]){
                q.push(j);
                a[j]=map[i][j]+a[i];
            }
        }
        q.pop();
    }
    if(a[e]!=1<<31)return a[e];
    else return 0;
}
int main(){
    freopen("a.txt","r",stdin);
    memset(map,0,sizeof(map));
    int q;
    scanf("%d%d%d",&n,&m,&q);
    while(m--){
        scanf("%d%d%d",&u,&v,&l);
        map[u][v]=l;
        map[v][u]=l;
    }
    while(q--){
        scanf("%d%d%d%d",&s,&e,&sl,&tl);
        int orz=spfa();
        int k=map[sl][tl];
        map[sl][tl]=0;
        if(orz==spfa())printf("N\n");
        else printf("Y\n");
        map[sl][tl]=k;
    }

}

不解释了。其实这道题完全不适合用spfa,这种解法只有50分封顶。但毕竟蒟蒻,骗分大发万岁!!!
暴力能得到 30 分. 看到数据 N 500,自然想到 Floyd 算法. 做 Floyd 的时候要记录两点最短路 d(i; j) 和最短路数量 f(i; j). 在判断边 x ! y 中断时,先判断 x ! y 是否在 s ⇝ t 的最短路中,即判断
d(s; x) + w(x; y) + d(y; t) = d(s; t)
是否成立. 若在最短路中,再判断
f(s; x) f(y; t) = f(s; t)
是否成立,即这条路是否是 s ⇝ t 最短路中必须经过的路.
这里写图片描述
这里写图片描述

好了,最后又回归第一题了

T1

签到题 checkin
题目背景 Background
“太阳当空照,花儿对我笑,小鸟说早早早,你为什么不去签个到?” 萌萌哒签到题来了,做完以后感觉整个人都萌萌哒 ≥ω≤
题目描述 Description
维护一个序列 支持1种操作
Opt:修改一个区间的值 整体+K
输入输出格式 Input/output
输入格式:
第一行一个正整数N,M 表示序列长度和操作个数
第二行N个正整数Ai 表示序列元素的初始值
以下M行 一行一个操作
形如 L R K 表示[L,R]整体+K.
输出格式:
输出操作后的序列.共1行.
输入输出样例 Sample input/output
样例测试点#1
输入样例: 在线IDE
5 3
1 2 3 4 5
2 4 3
3 5 1
1 2 2
输出样例:
3 7 7 8 6
说明 description
对于30%的数据 1≤N≤1000;1≤M≤1000;
对于60%的数据 1≤N≤100000;1≤M≤100000;
对于100%的数据 1≤N≤1000000;1≤M≤1000000;1≤Ai≤10000;1≤Ki≤10000;1≤L≤R≤N;
另外存在10%的数据 L=R;
数据保证运行中答案不会超出32位整数.
正如上文所说,这是一道树状数组ti。我不会,于是写了个大暴力。。。居然70分。。。

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
int t=0,n;
struct Node {
    int sum,lc,rc,delta;
}node[1000005];
void build(int now,int l,int r)
{
    node[now].sum=node[now].delta=0;
    if(l<r-1)
    {
        int mid=(l+r)>>1;
        node[now].lc=t;
        build(t++,l,mid);
        node[now].rc=t;
        build(t++,mid,r);
    }
    else node[now].lc=node[now].rc=0;
}
void update(int now,int l,int mid,int r)
{
    node[node[now].lc].delta+=node[now].delta;
    node[node[now].rc].delta+=node[now].delta;
    node[node[now].lc].sum+=node[now].delta*(mid-l);
    node[node[now].rc].sum+=node[now].delta*(r-mid);
    node[now].delta=0;
}
void change(int now,int l,int r,int lr,int rr,int delta)
{
    if (lr<=l&&r<=rr)
    {
        node[now].delta+=delta;
        node[now].sum+=(r-l)*delta;
        return;
    }
    int mid=(l+r)>>1;
    update(now,l,mid,r);
    if(lr<mid)change(node[now].lc,l,mid,lr,rr,delta);
    if(mid<rr)change(node[now].rc,mid,r,lr,rr,delta);
    node[now].sum=node[node[now].lc].sum+node[node[now].rc].sum;
}
int query(int now,int l,int r,int lr,int rr)
{
    if(lr<=l&&r<=rr)
        return node[now].sum;
    int mid=(l+r)>>1;
    int ans=0;
    update(now,l,mid,r);
    if(lr<mid)ans+=query(node[now].lc,l,mid,lr,rr);
    if(mid<rr)ans+=query(node[now].rc,mid,r,lr,rr);
    return ans;
}
int main()
{
    int m;
    scanf("%d%d",&n,&m);
    int root=t++;
    build(root,1,n+1);
    for(int i=1;i<=n;i++)
    {
        int a;
        scanf("%d",&a);
        change(root,1,n+1,i,i+1,a);
    }
    for(int i=1;i<=m;i++)
    {
        int lt,rt,a;
        scanf("%d%d%d",&lt,&rt,&a);
        change(root,1,n+1,lt,rt+1,a);
    }
    for(int i=1;i<=n-1;i++)
    {
        int ans=query(root,1,n+1,i,i+1);
        printf("%d ",ans);
    }
    int ans=query(root,1,n+1,n,n+1);
    printf("%d",ans);
    return 0;
}

这是线段树,又难写又容易卡最后一个点。

#include <cstdio>
#include <cstring>
using namespace std;
int c[1000500],f[1000500],a[1000500],s[1000500];
int n,m,i,j,k,opt,x,y,z,tmp1,tmp2;
int lowbit(int x)
{
    return x & (-x);
}
void insert(int pos,int v,int opt)
{
    while (pos<=n)
    {
        if (opt==1) c[pos]+=v;
        else f[pos]+=v;
        pos+=lowbit(pos);
    }
}
int sum(int pos,int opt)
{
    int ans = 0;
    while (pos>0)
    {
        if (opt==1) ans+=c[pos];
        else ans+=f[pos];
        pos-=lowbit(pos);
    }
    return ans;
}
int main()
{
    scanf("%d%d",&n,&m);
    for (i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
        s[i]=s[i-1]+a[i];
    }
    for (i=1;i<=m;i++)
    {
        scanf("%d%d%d",&x,&y,&z);
        insert(x,z,1); insert(y+1,-z,1);
        insert(x,z*x,2); insert(y+1,(-z)*(y+1),2);
    }
    for (i=1;i<=n;i++)
    {
        x=y=i;
        tmp1=sum(y,1)*(y+1)-sum(y,2)+s[y];
        tmp2=sum(x-1,1)*x-sum(x-1,2)+s[x-1];
        printf("%d ",tmp1-tmp2);
    }
    return 0;
}

这是能绝对AC的树状数组。。。

总结

这次考试(比赛),裸代码一定要背下来。。。实在不会一定要贪心骗分。。。不求AC多只求得分多。。。没错,文中出现的travis和shm都没有得高分。。。而且一次通过率极低,,,我以400分名居第二。YTYZ是弱校,莫打脸。
打这么久好累啊

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市需求。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值