2022暑期杭电第八场
文章目录
- 1001题
- Bragging Dice
- 题目大意
- 思路
- 代码
- 1007题
- Darnassus
- 题目大意
- 思路
- 代码
- 1008题
- Orgrimmar
- 题目大意
- 思路
- 代码
- 1011题
- Stormwind
- 题目大意
- 思路
- 代码
1001题
Bragging Dice
题目链接
题目大意
给一个只含01的字符串s,可以对任意的奇数长度区间翻转,可操作任意次数,输出s能变成的字典序最小的字符串。
思路
奇数长度翻转,意味着翻转后不改变奇偶性
所以每个 111 可以移动到任意同奇偶的位置
贪心地把 111 移到右边即可
具体看一组样例操作吧
发现答案由三部分组成,第一部分全是 000,第二部分 010101 交替,第三部分全是 111
我们分别统计在奇数位置和偶数位置上 111 的数量
然后按规律排列即可
代码
#include<bits/stdc++.h>
using namespace std;
string s;
void solve()
{int ji=0,ou=0;s="";cin>>s;int len=s.length();for(int i=0;i<len;i++){if(s[i]=='1') i&1 ? ou++ : ji++;}int minn=min(ji,ou);ji-=minn,ou-=minn;int tmp=len-minn*2-ji*2-ou*2;for(int i=1;i<=tmp;i++) printf("0");if(len&1) //奇后偶前{if(ji) for(int i=1;i<=ji;i++) printf("01");if(ou) for(int i=1;i<=ou;i++) printf("10");}else //奇前偶后{if(ji) for(int i=1;i<=ji;i++) printf("10");if(ou) for(int i=1;i<=ou;i++) printf("01");}for(int i=1;i<=minn;i++) printf("11");cout<<endl;
}
int main()
{int test;cin>>test; while(test--){solve();}
}
1007题
Darnassus
原题链接
题目大意
给你点的数量 n(n⩽50000)n(n \leqslant 50000)n(n⩽50000)和一个 1∼n1 \sim n1∼n 的排列p。点的标号从 111 到 nnn,点 iii 在排列 ppp 中对应的值为 p[i]p[i]p[i],任意两点间的边权为 ∣i−j∣×∣p[i]−p[j]∣|i − j|×|p[i] − p[j]|∣i−j∣×∣p[i]−p[j]∣ ,求最小生成树。
思路
nnn 的数量看起来不大,但边的数量是 n2n^2n2,prim和kruskal都不好处理,但也就边的数量过多这一个问题了,所以考虑删除一些不太可能成为树边的边。
观察可得点标号 iii 和排列中对应值 p[i]p[i]p[i] (以下简称为值)一一对应且计算边权时完全等价,将式子中差的绝对值视为距离,则可以很容易地发现距离越近则边权往往越小。由于 iii 和 p[i]p[i]p[i] 等价,所以需要同时考虑点在标号中的距离和在排列中的距离,选择距离较近的一些边跑最小生成树算法。
到这一步,问题已经可解,唯一没有确定的是“距离较近的边”具体有多近。不考虑证明的话,直接在可容许的时间复杂度内选择尽量远的边即可,推荐试一试常见数,比如 log2(n)log2(n)log2(n)、sqrt(n)sqrt(n)sqrt(n) 等等。由于生成树时每个点都要走一遍,所以基础复杂度就O(n)O(n)O(n)了,显然也没有多少数可以选择。别整成 n2n^2n2 就行
正解是 sqrt(n)sqrt(n)sqrt(n)。
因为我们可以令标号差或值差尽可能地小——也就是 111,然后另外一个顶天了也就是 n−1n-1n−1 ,所以最小生成树的边权不会大于等于 nnn 。还记得边权的公式吗?现在是 ∣i−j∣×∣p[i]−p[j]∣<n|i − j|×|p[i] − p[j]| < n∣i−j∣×∣p[i]−p[j]∣<n,显然只需要分别枚举 ∣i−j∣|i − j|∣i−j∣ 和 ∣p[i]−p[j]∣⩽n|p[i] − p[j]| \leqslant \sqrt[]{n}∣p[i]−p[j]∣⩽n 的部分就可以完整覆盖所有可能的边。
代码
#include<cstdio>
#include<cmath>
#include<cstring>
#include<queue>
using namespace std;
typedef long long ll;
inline int min(int a,int b)
{return a<b?a:b;
}
inline int max(int a,int b)
{return a>b?a:b;
}
int n,p[50005],rp[50005];
bool vis[50005];
int dis[50005];
ll prim()
{memset(vis,0,sizeof(vis));memset(dis,0x3f,sizeof(dis));int count=0,l,r,k=sqrt(n)+1; ll ans=0;priority_queue<pair<int,int> >q;q.push({0,(1+n)/2});dis[(1+n)/2]=0;while(1){int t=q.top().second;ll val=-q.top().first;q.pop();if(vis[t])continue;vis[t]=1;ans+=val;count++;if(count==n) return ans;l=max(1,t-k),r=min(n,t+k);for(int i=l;i<=r;i++) //枚举位置 {int dis2=abs((t-i)*(p[t]-p[i]));if(!vis[i] && dis2<dis[i]){q.push({-dis2,i});dis[i]=dis2;}}l=max(1,p[t]-k),r=min(n,p[t]+k);for(int i=l;i<=r;i++) //枚举值 {int dis2=abs((t-rp[i])*(p[t]-i));if(!vis[rp[i]] && dis2<dis[rp[i]]){q.push({-dis2,rp[i]});dis[rp[i]]=dis2;}}}
}
int main()
{int t; scanf("%d",&t);while(t--){scanf("%d",&n);for(int i=1;i<=n;i++){scanf("%d",p+i);rp[p[i]]=i;}printf("%lld\n",prim());}return 0;
}
1008题
Orgrimmar
原题链接
题目大意
求一棵树最大分离集的大小,换句话说,就是保留树的部分节点和他们之间的边,使得每个节点至多只有一条边与其相连,求点的集合的最大值。
思路
树形 dpdpdp ,可以发现父子节点之间有限制关系。令 fx,0/1/2{f_x,_{0/1/2}}fx,0/1/2 分别表示 xxx 为根的子树中,不选 xxx /选 xxx 但不选子节点连接/选 xxx 且选子节点连接,符合要求的集合最大值。
状态转移:
( yyy 为以 xxx 为根的子节点)
fx,0=sum(max(fy,0,fy,1,fy,2)){f_x,_0}=sum(max({f_y,_0},{f_y,_1},{f_y,_2}))fx,0=sum(max(fy,0,fy,1,fy,2))
fx,1=sum(fy,0)+1{f_x,_1}=sum({f_y,_0})+1fx,1=sum(fy,0)+1
fx,2=sum(fy,0)+max(fy′,1−fy′,0)+1{f_x,_2}=sum({f_y,_0})+max({f_{y'},_1}-{f_{y'},_0})+1fx,2=sum(fy,0)+max(fy′,1−fy′,0)+1
代码
#include<bits/stdc++.h>
using namespace std;typedef long long ll;
typedef double db;const int N=5e5+1;int T,n,tot,a,b;
int head[N],ver[2*N],Next[2*N],f[N][3];void add(int x,int y)
{ver[tot]=y;Next[tot]=head[x];head[x]=tot;tot++;
}void dfs(int x,int fa)
{int m0=0,m1=0,m2=0;//表示以x为根的三种情况for(int i=head[x];~i;i=Next[i]){int y=ver[i];if(y==fa) continue;dfs(y,x);//状态转移m0+=max(max(f[y][0],f[y][1]),f[y][2]);m1+=f[y][0];m2=max(m2,f[y][1]-f[y][0]);}f[x][0]=m0;f[x][1]=m1+1;f[x][2]=m1+m2+1;
}int main()
{int size(512<<20);__asm__ ( "movq %0, %%rsp\n"::"r"((char*)malloc(size)+size));scanf("%d",&T);while(T--){scanf("%d",&n);tot=0;for(register int i=1;i<=n;i++)//初始化{head[i]=-1;f[i][0]=0;f[i][1]=0;f[i][2]=0;}for(register int i=1;i<=n-1;i++){scanf("%d%d",&a,&b);add(a,b);add(b,a);}dfs(1,0);printf("%d\n",max(max(f[1][0],f[1][1]),f[1][2]));}exit(0);
}
1011题
Stormwind
题目链接
题目大意
给定一个 n×mn \times mn×m大小的矩形,要求画出尽可能多的线,使得按照这些线切割后得到的小矩形面积均 ⩾k\geqslant k⩾k,问最多能够画多少条线
思路
如果我们确定了某一方向上这条线的间隔时,依靠面积 kkk 即可求出另外一个方向上的间隔。那么我们只需要对某一个方向上的间隔进行枚举。随后计算出另外一个方向上的间隔,分别与 nmn mnm相除即可。值得注意的是,另一方向上的间隔大小应当向上取整,保证小矩形的面积 ⩾k\geqslant k⩾k
代码
#include<iostream>
#include<math.h>
using namespace std;void solve(){int n,m,k;cin>>n>>m>>k;int ans = 0;for(int i = 1;i <= k;i ++){double x = k*1.0 / i;int j = ceil(x);if(i > n || j > m)continue;ans = max(ans,n / i + m / j - 2);}cout<<ans<<endl;
}int main(){ios::sync_with_stdio(false);cin.tie(0);int t;cin>>t;while(t--)solve();system("pause");return 0;
}
2022暑期杭电第八场相关推荐
- 2022暑期杭电第十场
文章目录 1003题 Wavy Tree 题目大意: 思路: 参考代码: 1007题 Even Tree Split 题目大意 思路 代码 1009题 Painting Game 题目大意 分析 代码 ...
- 2022暑期杭电第七场
文章目录 1002题 Independent Feedback Vertex Set 题目大意: 思路: 代码: 1003题 Counting Stickmen 题目大意 思路 代码 1008题 tr ...
- 2022暑期杭电第三场
文章目录 1002题 Boss Rush 题意 分析 代码 1009 Package Delivery 题意 思路 代码 1011题 Taxi 题意: 思路: 代码 1012题 Two Permuta ...
- 2022暑期杭电第四场
文章目录 1001题 Link with Bracket Sequence II 题目大意 思路 代码 1003题 Magic 思路 代码 1001题 Link with Bracket Sequen ...
- 2022暑期杭电第九场
文章目录 1003题 Fast Bubble Sort 题目大意 思路 代码 1007题 Matryoshka Doll--线性DP 题目大意 思路 代码 1008题 Shortest Path in ...
- 2019暑期杭电多校HDU6599 I Love Palindrome String
2019杭电多校HDU6599 I Love Palindrome String 题目链接 I Love Palindrome String Time Limit: 4000/2000 MS (Jav ...
- 2022 年杭电多校第八场补题记录
A Theramore 题意:给定一个长度为 nnn 的 010101 串,每次可以选取一个奇数长度的连续子串进行位置上的翻转,问经过若干次操作能得到的字典序最小的串.n≤5×105n \leq 5\ ...
- 2019牛客暑期多校第八场 Flower Dance
题意 给一些点,找4个点,要求1个点在剩余三个点围成的三角形的内部,问方案数 题解 写得我有种不想碰几何的冲动.... 太迷了,精度迷,同一种意思的不同表达迷,明明那么简洁的思路,为什么写出来这么多特 ...
- 2021杭电多校第八场补题
比赛传送门:Contest Problem List (hdu.edu.cn) 1006)GCD Game 题目翻译:爱丽丝和鲍勃正在玩游戏. 他们轮流操作.有n个数字,a1,a2,...,an.每次 ...
最新文章
- CSS中关于margin的理解误区
- 理解Java动态代理(1)—找我还钱?我出钱要你的命
- 是否可以将Java 8用于Android开发?
- Linux平台下的内存泄漏检测
- linux的引导流程
- MCMC笔记:吉布斯采样(Gibbs)
- 高效CNN推理库、多款AlphaGo实现…你们喜欢的Github项目精选又来了!
- ES6新特性_Promise封装Ajax请求---JavaScript_ECMAScript_ES6-ES11新特性工作笔记026
- 小明用计算机算出58十35,人教版三年级数学下册第三四单元测试卷.docx
- gitlab syntax highlighting theme
- 初中计算机考试办公软件office2003安装教程
- 设置新版谷歌浏览器自动启用flash
- 网络摄像机如何安装拾音器?进行同步录音
- 海伦公式c语言double,海伦公式
- PowerDesigner显示工具栏
- ESP8266+电能计量芯片
- python连接hive
- VBA基础知识整理(数据类型)
- 基于JSP的网上购物系统的设计
- PJBlog 3.2.9.518 getwebshell 漏洞