2021“MINIEYE杯”中国大学生算法设计超级联赛(1)
2021“MINIEYE杯”中国大学生算法设计超级联赛(1)
1001 Mod, Or and Everything
题意:
对于每次输入的数字n,求(n%1)|...(n%n)的值
题解:
n%(n-i)=i,n偶数:m=(n/2-1)||n奇数:m=(n-1/2);0<=i<=m =>0|1|2|...|m
注意:
可以根据打表可知0|1|2...|m=pow(2,m上的最高数位)-1
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main(){
int t;cin>>t;
while(t--){
ll n;cin>>n;ll ans;
int i;ans=1;
for(i=1;i<=n;i++){
if(ans>=n)break;
else ans*=2;
}
i--;//n的最高数位
ans=pow(2,i-1)-1;//m的最高数位
cout<<ans<<endl;
}
return 0;
}
1002 Rocket land(待)
题意:
题解:
注意:
代码:
1003 Puzzle loop(待)
题意:
题解:
注意:
代码:
1004 Another thief in a Shop(待)
题意:
题解:
注意:
代码:
1005 Minimum spanning tree
题意:
求一个最小生成树
题解:
因为这棵树有一些特征,就是如果某个数是质数,就在前一个数的权值上加上自己x2,否则就加上自己x1。所以可以通过一个质数筛选出所有的质数,然后遍历,用一个数组存下来得到的值,之后只要直接读取就好了。
注意:
初始数据是down[2]=0
代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e7;
long long prime[maxn],down[maxn];bool v[maxn];
void primes()
{
memset(v,0,sizeof(v));
int m=0;//质数
for(int i=2;i<maxn;i++)
{
if(!v[i])prime[++m]=i;//质数
for(int j=1;j<=m&&prime[j]*i<=maxn;j++)
{
v[prime[j]*i]=true;//将倍数都赋给那些为合数的值
if(i%prime[j]==0)break;//已经进行过计算了
}
}
//for(int i=1;i<=m;i++)cout<<prime[i]<<" ";
}
int main(){
int t,n;
cin>>t;
primes();
down[2]=0;
for(int i=3;i<=maxn;i++){
if(v[i]==true)down[i]=down[i-1]+i;
else down[i]=down[i-1]+2*i;
}
while(t--)
{
cin>>n;
printf("%lld\n",down[n]);
}
return 0;
}
1006 Xor sum
题意:
找一个连续字串异或和大于等于k,有多组则输出左边起始点最小的字串左右序号
题解:
先求一个异或前缀和x,因为aba=b.所以某一段子串(n~m)的连续异或和就为x[n]^x[m],这里采用字典树的方式来维护运行,将前缀和用二进制的方式展开,插入字典树里边,去找两个数的前缀和异或>=k,记录下对应的编号,遍历下去找到最小的长度即可。
注意:
因为是多组输入,所以trie[][]数组里头有可能会有之前留下的数字,所以会造成一些问题,所以要进行初始化,但是用memset会T,所以这里采用,将下一个结点的trie[][]=0的形式
代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
#define INF 0x3f3f3f3f
int trie[maxn*31+10][2];//将一个数转换成二进制然后丢进字典树里边去维护
int index[maxn*31+10];//对于每一个数来说他们的二进制都是31位数的形式,所以插入的时候,是一个个把他们的数位插进去,所以tot会最多加到maxn*31次
int a[maxn];
int n,m,tot;
void insert(int x,int in)
{
int p=1;
for(int k=30;~k;k--)//(-1取反为0,可作为判断条件)
{
int ch=(x>>k)&1;
if(!trie[p][ch]){
trie[p][ch]=++tot;//trie开始用的就是1,所以要往下继续找结点,即2
trie[tot][0]=trie[tot][1]=0;//下一个结点是空的
}
p=trie[p][ch];
index[p]=in;//表示这一系列的数都是第in个数的插入结果
}
}
int find(int x)//得到的是与x异或的另外一个数的最小位置
{
int p=1;int res=0;
for(int k=30;~k;k--) {
int ch = (x >> k) & 1;
if (trie[p][ch ^ 1])//遍历的是另外一个数位和x完全不一样的数字,如果那个数字存在的话,就可以直接加上1<<k
{
p = trie[p][ch ^ 1];
res += 1 << k;
if (res >= m)return index[p];
}
else p=trie[p][ch];
}
return -1;
}
void solve()
{
scanf("%d%d",&n,&m);tot=1;
a[0]=0;int len=n+1,l,r;
trie[1][0]=trie[1][1]=0;
index[1]=1;//初始状态
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
if(a[i]>=m&&len!=1){
len=1;
l=r=i;
}
a[i]^=a[i-1];
}
if(len==1){
printf("%d %d\n",l,r);
return ;
}
int mit=INF;
for(int i=1;i<=n;i++)
{
int t=find(a[i]);//因为前一个数已经被插入进去了,所以直接搜就好了
if(~t&&i-t<mit)
{
mit=i-t;
l=t+1;
r=i;
}
insert(a[i],i);
}
if(mit==INF)printf("-1\n");
else printf("%d %d\n",l,r);
}
int main()
{
int t;
cin>>t;
while(t--)
{
solve();
}
}
1007 Pass!(待)
题意:
题解:
注意:
代码:
1008 Maximal submatrix
题意:
求连续的从上往下不递减的最大子矩阵的面积
题解:
悬线法,通过悬线的方式,左右移动找到最大的边界,用长度乘以悬线长度,即可求出面积
单调栈
注意:
开数组,稍微开大一点,这样不会越界
代码:
#include<bits/stdc++.h>
using namespace std;
int t,n,m;
const int maxn=2e3+5;//注意数组不要开太小,数组越界会显示T
int mt[maxn][maxn],k[maxn][maxn],l[maxn],r[maxn];
void solve()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
scanf("%d",&mt[i][j]);
for(int i=1;i<=m;i++)
{
stack<int>s;
for(int j=1;j<=n;j++)
{
if(s.empty()||mt[j][i]>=mt[s.top()][i])s.push(j);//连续不递减
else {
while(s.size()){
k[s.top()][i]=j-1;//因为到第j位出现断层,所以,每一条这样的悬线,他们的最长延伸长度都是j-1
s.pop();
}
s.push(j);//继续递归下去
}
}
while(s.size())//如果遍历到了末端,就说明,他们到了矩形的边界处
{
k[s.top()][i]=n;
s.pop();
}
for(int j=1;j<=n;j++)
{
k[j][i]-=j-1;//表示的是从底线j上边满足不递减的长度
}
}
int ans=0;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
l[j]=r[j]=j;//表示的是每条悬线所能移动的左右边界,滚动数组,减少空间
}
for(int j=1;j<=m;j++){
while(l[j]>1&&k[i][l[j]-1]>=k[i][j])//说明在第-1存在着一个障碍物
l[j]=l[l[j]-1];//所以它的左边界就要左移
}
for(int j=m;j;j--){
while(r[j]<m&&k[i][r[j]+1]>=k[i][j])
r[j]=r[r[j]+1];//l[j]==1||r[j]==m,表示在边界处,不需要再进行处理了
}
for(int j=1;j<=m;j++)
ans=max(ans,(r[j]-l[j]+1)*k[i][j]);
}
printf("%d\n",ans);
}
int main()
{
cin>>t;
while(t--)
{
solve();
}
return 0;
}
1009 KD-Graph
题意:
将一些点分成k块,并满足每一块里边都存在<=D,块与块之间满足>=D
题解:
最小生成树,通过不断寻找权值
注意:
并查集利用一下路径压缩,就不会T了
代码:
#include<bits/stdc++.h>
using namespace std;
int n,m,k;
const int maxn=1e6+10;
struct node{
int u,v,w;
//node(int _u,int _v,int _w):u(_u),v(_v),w(_w){}
}edge[maxn];
int f[maxn];
bool cmp(node a ,node b)
{
return a.w<b.w;
}
inline int find(int x)
{
return (x==f[x]?x:(f[x]=find(f[x])));//这里有一个路径压缩
//return x==f[x]?x:find(f[x]);
}
signed main()
{
int t;
cin>>t;
while(t--)
{
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=n;i++)f[i]=i;
for(int i=1;i<=m;i++){
scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].w);
}
sort(edge+1,edge+m,cmp);
int now=n,ans=0,flag=0;//????
for(int i=1;i<=m;i++)//权值是从小到大排列的
{
if(edge[i].w!=edge[i-1].w){//说明这个得到的ans就是上一组的权值
if(now==k){//已经分成了k块
printf("%d\n",ans);
flag=1;
break;
}
}
if(find(edge[i].u)==find(edge[i].v))continue;
now--;
f[find(edge[i].u)]=find(edge[i].v);//合并
ans=edge[i].w;//得到更大的权值,毫无疑问之前的分组的权值都是小于ans的
//而其他没有并进这些块的组很明显他们之间的权值都是要大于ans的
}
if(!flag){//表示中间有好几个相同权值的点,但是不知道他们有没有被并进去,需要判断
printf("%d\n",now==k?ans:-1);
}
}
return 0;
}
1010 Zoto
题意:
注意理解题意,这里是说有n次输入,每次输入一个数(i,a[i])作为点的x,y坐标,再进行m次查询,给定两个点的横坐标和纵坐标问查询的矩阵区域里头,有多少个y坐标不同的数。
题解:
了解了莫队算法之后,这道题目就可以转换成求一个区间内不同的数的个数了很轻而易举了,但是很明显还减去那些不在y1~y2之间的数,首先我们想到的就是直接暴力,对于l~r之间的点遍历,看他们是否在y1~y2这个区间里头,进行处理。没错没错,那肯定T了,所以作为一个有志向的Tlemer,我们要学会一些巧妙的算法,比如说树状数组,用树状数组来维护这个y坐标范围,getsum(y2)-getsum(y1-1)即是我们想要得到的答案
注意:
因为在树状数组里头都是以0作为退出while循环的判断数,所以对于y坐标而言,不能出现0的坐标,所以我们可以考虑将所有的y坐标+1.这样相对而言是没有变化的。
代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn = 2e6 + 5;
#define INF 0x3f3f3f3f
int block[maxn], cnt[maxn], a[maxn], c[maxn], res[maxn];
int t, n, m, s, l, r, num, unit;
int lowbit(int x) {
return x & (-x);
}
void updata(int i, int k) {
while (i <= n) {
c[i] += k;
i += lowbit(i);
}
}
int getsum(int i) {
int res = 0;
while (i > 0) {
res += c[i];
i -= lowbit(i);
}
return res;
}
void add(int x) {
if (!cnt[a[x]]) updata(a[x], 1);//用y坐标更新维护
cnt[a[x]]++;
}
void del(int x) {
cnt[a[x]]--;
if (!cnt[a[x]]) updata(a[x], -1);
}
struct query {
int l, r, n, ans, yl, yr;
} Q[maxn];
int cmp1(query a, query b) {
return (block[a.l] ^ block[b.l]) ? block[a.l] < block[b.l] : ((block[a.l] & 1) ? a.r < b.r : a.r > b.r);
}//更快,对于左端点在同一奇数块的区间,右端点按升序排列,反之降序。
int main() {
scanf("%d", &t);
while (t--) {
l = 1, r = 0;
scanf("%d%d", &n, &m);
s = sqrt(n);
unit = n / sqrt(m);
memset(cnt, 0, sizeof(cnt));
memset(c, 0, sizeof(c));
num = ceil((double) n / s);
for (int i = 1; i <= num; i++) {
for (int j = (i - 1) * s + 1; j <= s * num; j++)block[j] = i;
}
for (int i = 1; i <= n; i++)scanf("%d", &a[i]), a[i]++;//注:y坐标都加1是为了使y=0的情况不出现,因为y等于0的时候无法进行循环
for (int i = 1; i <= m; i++) {
scanf("%d%d%d%d", &Q[i].l, &Q[i].yl, &Q[i].r, &Q[i].yr);
Q[i].n = i;
Q[i].yl++, Q[i].yr++;
}
sort(Q + 1, Q + m + 1, cmp1);
for (int i = 1; i <= m; i++) {
while (l < Q[i].l)del(l++);
while (l > Q[i].l)add(--l);
while (r > Q[i].r)del(r--);
while (r < Q[i].r)add(++r);
res[Q[i].n] = getsum(Q[i].yr) - getsum(Q[i].yl - 1);
}
for (int i = 1; i <= m; i++)printf("%d\n", res[i]);
}
return 0;
}
1011 Necklace of Beads(待)
题意:
题解:
注意:
代码:
2021“MINIEYE杯”中国大学生算法设计超级联赛(1)的更多相关文章
- 2021“MINIEYE杯”中国大学生算法设计超级联赛(8)(1002,1004,1006,1009)
前言 依旧是白嫖账号,只打了一些题/kk 正题 1002 Buying Snacks 题目大意 \(n\)个物品,每个可以买一次也可以不买,如果买需要选择\(1/2\)块钱的,然后也可以相邻两个一起买 ...
- 2021“MINIEYE杯”中国大学生算法设计超级联赛(7)部分题解
前言 找大佬嫖到个号来划水打比赛了,有的题没写或者不是我写的就不放了. 目前只有:1004,1005,1007,1008,1011 正题 题目链接:https://acm.hdu.edu.cn/con ...
- 2022“杭电杯”中国大学生算法设计超级联赛(6)- 1011 Find different
2022"杭电杯"中国大学生算法设计超级联赛(6)- 1011 Find different 比赛时队友开摆,还剩半个小时,怎么办?? 当然是一起摆 Solution 看到这个题没 ...
- 3I工作室的成员在2013年(第6届)中国大学生计算机设计大赛总决赛中荣获全国二等奖
在暑假举行的2013年(第6届)中国大学生计算机设计大赛中,我院的参赛作品<毕业生论文选导系统>(作者:祝丽艳/许明涛:指导老师:元昌安/彭昱忠)入围总决赛,并荣获全国二等奖. 2013年 ...
- "巴卡斯杯" 中国大学生程序设计竞赛 - 女生专场
Combine String #include<cstdio> #include<cstring> #include<iostream> #include<a ...
- hdu_5705_Clock("巴卡斯杯" 中国大学生程序设计竞赛 - 女生专场)
题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=5705 题意:给你一个时间和一个角度,问你下一个时针和分针形成给出的角度是什么时候 题解:我们可以将这个 ...
- hdu_5707_Combine String("巴卡斯杯" 中国大学生程序设计竞赛 - 女生专场)
题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=5707 题意:给你三个字符串 a,b,c,问你 c能否拆成a,b,a,b串的每一个字符在c中不能变 题解 ...
- 2017年“嘉杰信息杯” 中国大学生程序设计竞赛全国邀请赛 Highway
Highway Accepted : 122 Submit : 393 Time Limit : 4000 MS Memory Limit : 65536 KB Highway In ICPC ...
- 2017年全国大学生物联网设计竞赛(TI杯)华东分赛区决赛总结
全国大学生物联网设计竞赛(TI杯)是由教育部高等学校计算机类教学指导委员会主办.上海交通大学电子信息与电气工程学院承办.德州仪器半导体技术公司(TI)协办的赛事,自2014年设立以来,一直是物联网领域 ...
- HDU 5943 Kingdom of Obsession 【二分图匹配 匈牙利算法】 (2016年中国大学生程序设计竞赛(杭州))
Kingdom of Obsession Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Oth ...
随机推荐
- 二.安装ifconfig命令
二.安装ifconfig命令 1.ifconfig命令是设置或显示网络接口的程序,可以显示出我们机器的网卡信息,可是有些时候最小化安装CentOS等Linux发行版的时候会默认不安装ifconfig等 ...
- cadence软件画版图操作
cadence软件操作 1.原理图设计 电路的原理图设计和许多的电路设计软件是类似的,这里大致介绍一下基本的操作. 首先是新建一个cell的原理图: library manager>file&g ...
- BorderDet:通过边界特征大幅提升检测准确率,即插即用且速度不慢 | ECCV 2020 Oral
边界对于定位问题十分重要,BorderDet的核心思想BorderAlign巧妙又有效,将边界特征融入到目标定位预测中,而且能够简单地融入到各种目标检测算法中带来较大的性能提升下.在开源实现中,对Bo ...
- KingbaseES 临时表
临时表在数据库管理和数据处理中有着广泛的应用,主要用于存储临时数据或进行中间计算.临时表中的数据对会话是私有的,每个会话只能看到和修改自己会话的数据. KingbaseES支持本地临时表和全局临时表. ...
- linux xfce 设置限制亮度滑块的最小亮度,在屏幕里的xfce设置亮度的最小亮度。
参照 https://docs.xfce.org/xfce/xfce4-power-manager/preferences 使用代码 xfconf-query -c xfce4-power-manag ...
- wordpress自建博客站,为文章添加显示浏览次数功能
wordpress自建博客站,为文章添加显示浏览次数功能 笔者使用的主题是 GeneratePress 版本:3.1.3 1.后台文章管理列表添加浏览次数列 效果如图: 实现: 编辑funct ...
- #Splay#洛谷 1486 [NOI2004]郁闷的出纳员
题目 分析 考虑加减工资直接打标记,查询第\(k\)多可以用平衡树, 删除有点恶心,这里考虑Splay,将需要删除的部分的后继splay到根节点并将左子树断边 代码 #include <cstd ...
- Jetty的https模块
启用https模块,执行如下命令: java -jar $JETTY_HOME/start.jar --add-modules=https 命令的输出,如下: INFO : https initial ...
- 深度剖析 Spring 框架在 Java 应用开发中的优势与应用
Spring 是用于企业 Java 应用程序开发的最流行的应用程序开发框架.全球数百万开发人员使用 Spring Framework 创建高性能.易于测试和可重用的代码.Spring Framewor ...
- go切片和指针切片
转载请注明出处: 在Go语言中,切片(Slice)和指针的切片(即切片中每个元素都是指向某种数据类型的指针)是两个不同的概念,它们各自具有特定的用途和优势. 切片(Slice) 切片是对数组的一个连续 ...