A.Oops, It’s Yesterday Twice More

题目链接:https://codeforces.com/gym/103470/problem/A

题意:给定一个n*n的方格,每个方格中可能会有袋鼠,你需要操作所有的袋鼠使得最后所有的袋鼠都能够到达(a,b),给出一种操作次数不超过3*(n-1)的操作方案。每次操作我们都会使得所有的袋鼠向一个方向移动,不能移动的袋鼠就不移动。ULDR为操作的命令

分析:我们首先需要将所有的袋鼠移动到同一个位置,然后再统一移动所有的袋鼠,我们可以将所有的袋鼠都移动到四个角落的某一个角落,具体移动到哪个角落取决于(a,b)距离哪个角落更近。

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<vector>
#include<queue>
using namespace std;
const int N=2e5+10;
int main()
{int n,a,b;cin>>n>>a>>b;if(a<=n/2)//上半面 {if(b<=n/2)//左上{for(int i=1;i<n;i++)printf("LU");for(int i=1;i<a;i++)printf("D");for(int i=1;i<b;i++)printf("R");}else//右上 {for(int i=1;i<n;i++)printf("RU");for(int i=1;i<a;i++)printf("D");for(int i=1;i<=n-b;i++)printf("L");}}else//下半面 {if(b<=n/2)//左下 {for(int i=1;i<n;i++)printf("LD");for(int i=1;i<=n-a;i++)printf("U");for(int i=1;i<b;i++)printf("R");}else//右下 {for(int i=1;i<n;i++)printf("RD");for(int i=1;i<=n-a;i++)printf("U");for(int i=1;i<=n-b;i++)printf("L");}}return 0;
}

C. Klee in Solitary Confinement

题目链接:Problem - C - Codeforces

样例输入:

9 -100
-1 -2 1 2 -1 -2 1 -2 1

样例输出:

3

题意:给你一个长度为n的数组和一个整数k,我们可以对数组进行操作,但是操作次数不得超过1,操作就是选择一个区间[l,r],把位于这个区间内的所有数都加上k,现在问我们操作后数组中出现次数最大的数的出现次数的最大值。

分析:对于每一个a[i]我们求一下他对a[i]+k产生的最大有效贡献即可。什么叫最大有效贡献呢?假如我们选定的区间中有p个a[i],q个a[i]+k,那么有效贡献就是p-q,这是比较容易理解的,因为操作后会多产生p-q个a[i]+k,所以我们只要遍历一下每一个a[i]即可,最后过程中记录一下最大值即可。关键是怎么求最大有效贡献呢?我们首先记录一下a[i]的出现位置并存入一个数组中,同理记录一下a[i]+k的出现位置并存入另一个数组中,对这两个数组进行从小到大排序,并设置两个指针分别指向两个数组的起始位置,然后每次选择一个靠前的位置,如果是a[i]靠前,那么我们就令贡献+1,否则令贡献-1,并移动相应的指针,如果贡献一旦减为负数,那么就令贡献为0,这个思想就是类似于最大子段和,最后在过程中记录一下每个a[i]的最大有效贡献即可。

需要特别注意的一点就是k=0的情况,这个时候直接取出现次数最大的数的出现次数作为答案即可。

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<vector>
#include<queue>
using namespace std;
const int N=4e6+10;
vector<int>p[N];
vector<int>alls;
int main()
{int n,k;cin>>n>>k;int t;for(int i=1;i<=n;i++){scanf("%d",&t);p[t+2000001].push_back(i);alls.push_back(t+2000001);}sort(alls.begin(),alls.end());alls.erase(unique(alls.begin(),alls.end()),alls.end());int ans=0;for(int i=0;i<alls.size();i++){ans=max(ans,(int)p[alls[i]].size());if(k==0) continue; if(p[alls[i]+k].size()==0) continue;int f=0;//计算最多可以将多少个alls[i]变为alls[i]+k int nowf=0;//计算当前贡献 int l1=0,l2=0;int len1=p[alls[i]].size(),len2=p[alls[i]+k].size();while(l1<len1&&l2<len2){if(p[alls[i]][l1]<p[alls[i]+k][l2]){nowf++;f=max(f,nowf);l1++;}else{nowf--;if(nowf<0) nowf=0;l2++;}}if(l1!=len1){nowf+=len1-l1;f=max(f,nowf);}ans=max(ans,f+len2);}printf("%d",ans);return 0;
}

D.Paimon Sorting

题目链接:https://codeforces.com/gym/103470/problem/D

样例输入:

3
5
2 3 2 1 5
3
1 2 3
1
1

样例输出:

0 2 3 5 7
0 2 4
0

题意:给定一个长度为n的数组,然后给定一个排序代码,我们需要利用上述代码对原数组进行排序,问交换次数,输出是针对前k个元素排序的交换次数,输出k=1,2,……,n情况下的交换次数。

分析:先考虑对前k个元素进行排序的结果,对于i从1~k遍历,第i次遍历完的数组一定有前i个元素有序,那么我们下一次就是对第i+1个元素进行遍历交换,比如前i次排序后的结果是

2 5 8 8 9 6,其中i等于4,下一次对第5个位置进行排序,那么我们会先用6和8交换,然后再用8和9交换,得到2 5 6 8 8 9,交换次数是2,交换次数就是大于6的不重复的连续的元素个数,这个刚好可以用树状数组进行维护,所以对于固定前k个元素的情况我们可以O(klogk)解决,关键是我们怎么由k的答案得到k+1时的答案,因为我们加入第k+1个数时,这个时候我们需要对第k+1个数进行讨论,如果第k+1个数小于等于前k个数的最大值,那么我们可以知道在前k轮排序过程中是不会涉及到第k+1个数的,因为最大值之后的数是不可能发生交换的,那么只有在第k+1轮排序时才会对第k+1个数进行交换,那么他会交换多少次呢?因为第k+1次排序时前k个数已经有序了,这个时候在前k个数中有多少个不同且比第k+1个数大的数那么就会交换多少次,这个很容易讨论。关键是第k+1个数大于前k个数的最大值时我们需要多加思考一下,因为我们在对第一个数排序时,就会把第k+1个数放置在第一个位置,那么对于第一个位置的前k次排序时不会涉及到第k+1个数,但是当拿前k个数的最大值与第k+1个数比较时还会交换一次,所以会多交换一次,而且被交换到第k+1个位置上的数在对前k个数进行交换时不会再涉及到,这个时候我们可以把第k+1个数作为一个新的最大值进行考虑,并不影响中间过程的交换次数,但是当对第k+1个位置排序时还会涉及到一次,所以共涉及到2次,这是在前k个的最大值只出现一次的情况,如果前k次的最大值不只是出现一次,那么我们能够发现,由于原来前k个数中有多个最大值,而最大值与最大值是不会进行交换的,但是现在最大值变得更大了,因为最大值第一次出现的位置在一开始就挪至第k+1个数的位置了,那么从第二次出现最大值的位置往后,每个数都会多交换一次就是在遍历到这个位置的时候会多交换一次,这个答案我们必须要记录。这个地方需要找个数组仔细模拟一下。

细节见代码:

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<vector>
#include<queue>
using namespace std;
const int N=2e5+10;
int a[N],c[N];
int lowbit(int x)
{return x&-x;
}
void add(int x)
{for(int i=x;i<N;i+=lowbit(i))c[i]++;
}
int sum(int x)
{int ans=0;for(int i=x;i;i-=lowbit(i))ans+=c[i];return ans;
}
int main()
{int T;cin>>T;while(T--){int n;scanf("%d",&n);for(int i=1;i<=n;i++) c[i]=0;for(int i=1;i<=n;i++)scanf("%d",&a[i]);long long ans=0;printf("%lld",ans);int mx=a[1];add(a[1]);int cnt=1;//记录当前树状数组中有多少个不重复元素 vector<int>p;//记录最大值出现的位置p.push_back(1);for(int i=2;i<=n;i++){if(a[i]<=mx){ans+=cnt-sum(a[i]);if(a[i]==mx)p.push_back(i);}else{if(p.size()==1)ans+=2;elseans+=2+i-p[1];mx=a[i];p.clear();p.push_back(i);}if(sum(a[i])-sum(a[i]-1)==0)add(a[i]),cnt++;printf(" %lld",ans);}puts("");}return 0;
}

H. Crystalfly

题目链接:Problem - H - Codeforces

样例输入:

2
5
1 10 100 1000 10000
1 2 1 1 1
1 2
1 3
2 4
2 5
5
1 10 100 1000 10000
1 3 1 1 1
1 2
1 3
2 4
2 5

样例输出:

10101
10111

题意:给定一个有n个节点的有根树,根节点为1,每个节点i上有a[i]只苍蝇,还有一个对应的反应时间t[i],有个人一开始位于根节点,如果一旦人第一次到达i节点,那么i节点的所有子节点j上的苍蝇会在时间t[j]后飞走,人每到达一个节点,如果这个节点的苍蝇还没飞走就会把所有的苍蝇全部抓住,当反应时间还剩0s时人到达了,那么是人先抓苍蝇,问人最多能够抓到的苍蝇数目。

每个苍蝇的反应时间是小于等于3的。

分析:我们先来看一下这个3是干什么的。

以这个图为例,我们从1->2->1花费时间就是2s,那么我们下一秒从1->3需要花费1s, 那么总时间就是3s,也就是说我们对于每一个节点最多抓到他两个子节点上的苍蝇,前提还得是第二个节点的苍蝇的反应时间是3s,否则只能抓到一个节点的苍蝇。那么很显然如果1有更多的子节点,则其他子节点上的苍蝇都要飞走了,但其子节点的子节点上的苍蝇并不会受到影响,我们来看一下这样操作后对2号节点和3号节点的影响,因为我们是先到达了一次2节点,那么等我们返回1后,等下次再到2号节点时,会发现2号节点的所有子节点上的苍蝇都已经飞走了,而我们到达3号节点后我们就可以继续抓其子节点上的苍蝇。

树形DP含义:

f[i][0]代表第i个结点无贡献且其子节点苍蝇全部飞走的贡献 
f[i][1]代表第i个结点无贡献但其子节点全部未受干扰的贡献

那么答案就是a[1]+f[1][1].

如果当前节点的子节点中有反应时间为3s的子节点,那么我们就有可能存在上述情况,否则是不会存在上述回溯的过程的,如果不存在回溯的过程,我们直接选择一个子节点权值最大的点进行递归即可,否则我们需要找到上图中的2号点和3号点,对于除了这两个点之外的其他子节点j我们都是取f[j][1],因为我们还没有到达子节点j,那么j的子节点是不可能受到干扰的,而3号点由于是后到达的,那么我们要加上3号点的权值,也等价于3号点的子节点是不受到干扰的,因为刚开始干扰,而且下一秒我们就开始考虑3号点的子节点了,所以这里我们只需要多加一个3号点的点权即可。但是2号节点不一样,如果我们不访问2号节点的话,那么2号点的贡献是f[2][1],但是我们访问2号点之后2号点的贡献就是a[2]+f[2][0],所以新增的贡献就是a[2]+f[2][0]-f[2][1],我们只需要记录最大值次大值及其编号即可,而对于子节点反应时间为3s的节点我们也需要统计一下点权的最大值和次大值及其对应的编号即可,为什么都需要记录次大值呢?防止2号点和3号点的最大值对应的点是同一个,我们求出来的这两个贡献取一个加和最大值计入贡献即可。把最大贡献加入f[x][1]即可。

更新f[x][0]:因为x的所有子节点都已经飞走,那么我们什么时候到达其子节点意义不大,我们子需要取其子节点j中f[j][0]和f[j][1]的最大值即可。

更新f[x][1]:一开始默认所有的子节点j都取f[j][0]和f[j][1]的最大值即可,因为一开始也是默认子节点都不进入,我们只是最后选择两个节点来进行更新最优值,最后直接把新加的贡献计入f[x][1]即可。

细节见代码:

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<vector>
#include<queue>
using namespace std;
const int N=2e5+10;
int h[N],e[N],ne[N],idx;
int a[N],t[N];
long long f[N][2];
vector<int> p[N];//p[i]记录第i个结点的子节点中时间等于3的结点
//f[i][0]代表第i个结点无贡献且其子节点苍蝇全部飞走的贡献?
//f[i][1]代表第i个结点无贡献但其子节点全部未受干扰的贡献
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*10+c-'0',c=getchar();return x*f;
}
void add(int x,int y)
{e[idx]=y;ne[idx]=h[x];h[x]=idx++;
}
void dfs(int x,int fa)
{f[x][0]=f[x][1]=0;int mx1=0,id1=-1;//记录子节点为3s的节点的点权的最大值和对应的编号int mx2=0,id2=-1;//记录子节点为3s的节点的点权的次大值和对应的编号int mx3=0,id3=-1;//记录子节点的a[j]+f[j][0]-f[j][1]的最大值和对应的编号int mx4=0,id4=-1;//记录子节点的a[j]+f[j][0]-f[j][1]的次大值和对应的编号int mx=0;//记录子节点点权最大值
//  priority_queue<pair<long long,int> >q;for(int i=h[x];i!=-1;i=ne[i]){int j=e[i];if(j==fa) continue;dfs(j,x);if(t[j]==3){if(a[j]>mx1){mx2=mx1;id2=id1;mx1=a[j];id1=j;}else if(a[j]>mx2){mx2=a[j];id2=j;}}mx=max(mx,a[j]);if(a[j]+f[j][0]-f[j][1]>mx3){mx4=mx3;id4=id3;mx3=a[j]+f[j][0]-f[j][1];id3=j;} else if(a[j]+f[j][0]-f[j][1]>mx4){mx4=a[j]+f[j][0]-f[j][1];id4=j;}f[x][0]+=f[j][1];f[x][1]+=max(f[j][0],f[j][1]);}long long ans=f[x][1]+mx;if(id1!=-1)//代表子节点中有3s的{if(id3!=id1)ans=max(ans,f[x][1]+mx3+mx1);else{if(id2==-1)//3s的孩子结点只有一个 ans=max(ans,f[x][1]+mx4+mx1);elseans=max(ans,f[x][1]+max(mx1+mx4,mx2+mx3));}}f[x][1]=ans;
}
int main()
{int T;cin>>T;while(T--){idx=0;int n;scanf("%d",&n);for(int i=1;i<=n;i++)scanf("%d",&a[i]),h[i]=-1;for(int i=1;i<=n;i++)scanf("%d",&t[i]);for(int i=1;i<n;i++){int u,v;scanf("%d%d",&u,&v);add(u,v);add(v,u);}dfs(1,-1);printf("%lld\n",f[1][1]+a[1]);}return 0;
}

M. Windblume Festival

题目链接:Problem - M - Codeforces

样例输入:

5
4
1 -3 2 -4
11
91 66 73 71 32 83 72 79 84 33 93
12
91 66 73 71 32 83 72 79 84 33 33 93
13
91 66 73 71 32 83 72 79 84 33 33 33 93
1
0

样例输出:

10
713
746
779
0

题意:给定一个长度为n的数组,你可以把这个数组看成是一个环形的,每次我们选择两个数进行合并,合并后的结果就是前一个数减去后一个数,问最后剩一个数时这个数最大能是多少。

分析:先假设我们最后剩余的数的位置是i,那么我们让第i个位置放在第一个位置,按照这个顺序对原数组进行一次重排,不妨设排序后的数组就是a[1~n]。

我们现在有a[1]  a[2]  ……  a[n]

我们现在就等价于在每一个位置前放一个符号,然后进行运算得到最后的结果就行。

那么每一个位置前面的正负号是随意的吗?答案是不完全是,除了前两个数之外的数的正负号可以随意加,因为第一个数前面必须是+,而第二个数前面必须是-,这是运算规则决定的,但是对于第i个数,如果我们想让其为+,那么我们可以先让其与第i-1个数进行一次操作,然后就变为了正号,最后直接从前往后依次选择相邻的两个数进行操作即可

比如我们现在想构造a[1]-a[2]-a[3]+a[4]+a[5]

那么我们从第2个数往后考虑,考虑前面是正号的数,那么发现第一个数是a[4],那么就先让他与前面一个数进行一次操作得到 a[1]  a[2]  a[3]-a[4] a[5]

发现a[5]前面也是正数,所以我们也让a[5]与其前面的数a[3]-a[4]进行一次操作得到a[1]  a[2]  a[3]-a[4]-a[5],剩下的都是负号了,我们直接从前往后依次选择两个数进行操作即可。

得到a[1]-a[2]-(a[3]-a[4] a[5])=a[1]-a[2]-a[3]+a[4]+a[5]

所以我们最后只需要选择两个相邻的数前一个取正号,后一个取负号,其余的数全部取绝对值即可,最后直接暴力枚举最大值即可

下面是代码:

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<vector>
#include<queue>
using namespace std;
const int N=1e6+10;
int a[N];
int main()
{int T;cin>>T;while(T--){int n;scanf("%d",&n);long long s=0,ans=-0x3f3f3f3f3f3f3f3f;for(int i=1;i<=n;i++)scanf("%d",&a[i]),s+=abs(a[i]);if(n==1){printf("%d\n",a[1]);continue;}for(int i=1;i<=n;i++)ans=max(ans,s-abs(a[i])-abs(a[i%n+1])+(a[i]-a[i%n+1]));printf("%lld\n",ans);}return 0;
} 

2021icpc南京站相关推荐

  1. 2021ICPC南京站大杂记

      发现自己真的好久没写游记了啊...倒是各式各样的其他小作文写了不少,甚至发现 csdn 这鬼东西还能发动态... 前言   真没想到吧,大四了还没退役.以前中学说"五年 OI 一场空&q ...

  2. 一本跳进挨踢生活圈的日记(南京站)

    2013年5月8日 星期三  天气:各种雨量随机播放中 51CTO账号: sliver098 51CTO博客: http://slivery.blog.51cto.com/ QQ: 298032098 ...

  3. 数据中心供配电技术巡展南京站成功举办

    南京是中国著名的四大古都及历史文化名城之一.千百年来,奔腾不息的长江不仅孕育了长江的文明,也催生了南京这座江南城市.南京襟江带河,依山傍水,钟山龙蟠,石头虎踞,山川秀美,古迹众多,依托得天独厚的历史文 ...

  4. 百度AI快车道南京站来了!接力魔都,继续听前沿技术、学最IN的解决方案

    某Boss:怎样才能长寿? 某程序猿:当程序员! 某Boss:干程序员还能增加寿命? 某程序猿:这行干久了,你就像7.80岁的老头了. 的确,程序员是个体力活,几乎每天都在"前期大量编程,后 ...

  5. AIoT催使AI深度场景化,“AI赋能,智联万物——开发者沙龙·南京站”圆满落幕...

    AIoT不是1+1=2,而是1+1.2. 1月24日,"AI赋能,智联万物--开发者沙龙·南京站"正式圆满落幕,此次活动由涂鸦智能主办.镁客网承办.InnoSpace协办,旨在通过 ...

  6. openEuler Meetup 南京站 | 麒麟信安加入南京用户组,分享《CentOS原地透明迁移方案技术实践》

    11月11日下午,由openEuler 社区.江苏鲲鹏·昇腾生态创新中心主办的openEuler Meetup南京站于线上线下同步举行.本次Meetup集聚社区开发者.用户.企业伙伴.操作系统爱好者, ...

  7. 聚力远谋,创赢未来 | 坤前全国巡展南京站圆满收官

    12月10日,"聚力远谋,创赢未来"2021坤前生态合作伙伴交流会全国巡展南京站正式拉开帷幕,坤前的核心客户及生态合作伙伴齐聚一堂,共话数字时代产业发展. 会议伊始,坤前计算机总裁 ...

  8. 百度飞桨中国行南京站开启!共研AI赋能产业新模式

    面对未来发展,以人工智能为代表的新一代技术逐渐成为产业转型的核心驱动力之一,人工智能的发展离不开创新和人才.在这一大背景下,百度推出"飞桨中国行"活动,计划走入全国多个 AI 重点 ...

  9. 求职(2015南京站获得百度、美的集团、趋势科技、华为offer)

    版权所有所有:没有马缰绳chhuach(CSDN博客源).转载请注明出处. 禁止www.haogongju.net转载. 特此声明 一.开篇: 9月底,找工作接近尾声,笔者主要经历了2015年南京站百 ...

最新文章

  1. 2020年春季信号与系统试卷批改
  2. c#获取电脑硬件信息参数说明(主板篇 Win32_BaseBoard )
  3. python实现简易版成绩管理系统_Python 实现简易版成绩管理系统!
  4. hdu 5616 Jam's balance 正反背包+转换
  5. android adb杀死服务,Android app是如何杀掉的
  6. API 层实现语音录制
  7. 【转载】解决telnet无法连接 Connection refused
  8. 小程序实战1-项目总览
  9. 24速算c语言实训报告ppt,C语言课程设计(速算24).doc
  10. hi3559AV100上交叉编译faiss(facebook research)
  11. 【SDCC 2016】微影时代、普元、亚信、Fit2Cloud、VMware、京东商城、优维科技畅聊自动化运维与容器...
  12. 如何搭建一对一直播PHP直播系统源码的流程
  13. python内置函数dict()
  14. python中判断小写字符_Python islower()函数 判断字符串中字符是否都为小写
  15. 多关键词匹配个人解决方案
  16. mysqlin查询的java写法_[转载]常用的shell脚本
  17. # **PS CC2019 安装破解教程**
  18. 计算机网络学习16:以太网交换机自学习与帧转发流程、生成树协议STP
  19. 22、Java——汽车租赁系统(对象+集合)
  20. D3D Surface/Texture SDL DDraw渲染视频的区别和疑问

热门文章

  1. docker看远程仓库镜像_查看Docker镜像仓库中镜像的所有标签
  2. 一张图理解内网、外网、动态IP
  3. TeamViewer 下载和安装使用
  4. 使用Python+Selenium进行物流中转次数研究
  5. 你知道同声翻译手机软件哪个好吗?三招教你实现同声翻译
  6. c语言dll注入器,教大家写一个远程线程的DLL注入,其实还是蛮简单的……………………...
  7. Vue实战狗尾草博客管理系统第二章
  8. 清平调·其一 李白
  9. 【Docker】windows环境下的docker如何开放远程2375端口
  10. 方寸知识篇 - 数字图像处理(四)- FPGA与图像处理