洛谷 3322 [SDOI2015]排序

题目

小A有一个\(1\sim 2^N\)的排列\(A[1\sim 2^N]\),他希望将A数组从小到大排序,小A可以执行的操作有\(N\)种,每种操作最多可以执行一次,

对于所有的\(i(1<=i<=N)\),第\(i\)种操作为将序列从左到右划分为\(2^{N-i+1}\)段,每段恰好包括\(2^{i-1}\)个数,然后整体交换其中两段.

小A想知道可以将数组A从小到大排序的不同的操作序列有多少个,小A认为两个操作序列不同,当且仅当操作个数不同,或者至少一个操作不同(种类不同或者操作位置不同)。


分析

操作顺序不影响答案(这里不算操作位置)

答案乘阶乘,也就是操作顺序改变虽然操作位置改变

但是仍然可以通过一次搜索计算

因为第\(i+1\)次操作不能改变第\(i\)次操作(内部不会改变)

所以分四种情况讨论

1.所有段连续递增(继续搜索下一次操作)

2.有一个段没有连续递增(切开一半判断递增,继续搜索)

3.有两个段没有连续递增(两段各交换一半判断递增,继续搜索)

4.有三个或以上的段没有连续递增(显然无解)

所以代码就出来了


代码

  1. #include <cstdio>
  2. #include <cctype>
  3. #define rr register
  4. using namespace std;
  5. int a[4096],er[13],n; long long jc[13],ans;
  6. inline signed iut(){
  7. rr int ans=0; rr char c=getchar();
  8. while (!isdigit(c)) c=getchar();
  9. while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
  10. return ans;
  11. }
  12. inline bool check(int st,int m){
  13. for (rr int i=st+1;i<st+er[m];++i)
  14. if (a[i-1]+1!=a[i]) return 0;
  15. return 1;
  16. }
  17. inline void Swap(int &a,int &b){a^=b,b^=a,a^=b;}
  18. inline void Twap(int l1,int l2,int m){for (rr int i=0;i<er[m];++i) Swap(a[l1+i],a[l2+i]);}
  19. inline void dfs(int dep,int now){
  20. if (dep>n) {ans+=jc[now]; return;}
  21. rr int pos1=-1,pos2=-1;
  22. for (rr int i=0;i<er[n];i+=er[dep])
  23. if (!check(i,dep)){
  24. if (pos2==-1) pos2=pos1,pos1=i;
  25. else return;
  26. }
  27. if (pos1==-1&&pos2==-1) dfs(dep+1,now);
  28. else if (pos2==-1){
  29. Twap(pos1,pos1+er[dep-1],dep-1);
  30. if (check(pos1,dep)) dfs(dep+1,now+1);
  31. Twap(pos1,pos1+er[dep-1],dep-1);
  32. }else{
  33. for (rr int k1=0,flag=0;k1<2;++k1)
  34. for (rr int k2=0;k2<2;++k2){
  35. Twap(pos1+k1*er[dep-1],pos2+k2*er[dep-1],dep-1);
  36. if (check(pos1,dep)&&check(pos2,dep)) dfs(dep+1,now+1),flag=1;
  37. Twap(pos1+k1*er[dep-1],pos2+k2*er[dep-1],dep-1);
  38. if (flag) {flag=0; break;}
  39. }
  40. }
  41. }
  42. signed main(){
  43. n=iut(),er[0]=jc[0]=1;
  44. for (rr int i=1;i<=n;++i)
  45. er[i]=er[i-1]<<1,jc[i]=jc[i-1]*i;
  46. for (rr int i=0;i<er[n];++i) a[i]=iut();
  47. dfs(1,0);
  48. return !printf("%lld",ans);
  49. }

洛谷 3320 [SDOI2015] 寻宝游戏

题目


分析

首先答案就是所有有宝藏(关键点)所构成的极小连通子树的边权和两倍

然后从哪一个点开始最小答案应该都是一样的,所以考虑从dfs序最小的开始,

沿着dfs序依次求两点间距离,用set维护该点dfs序的前驱和后继,

如果该点不存在前驱或后继那么把它变成最后一个点或最前一个点,

因为题目说到要返回,也就是最后一个点要回到第一个点


代码

  1. #include <cstdio>
  2. #include <cctype>
  3. #include <set>
  4. #define rr register
  5. using namespace std;
  6. const int N=100101; struct node{int y,w,next;}e[N<<1]; set<int>uk; set<int>::iterator it; bool v[N];
  7. int k=1,n,m,ls[N],root,fat[N],nfd[N],dep[N],son[N],dfn[N],top[N],big[N],tot; long long W[N],ans;
  8. inline signed iut(){
  9. rr int ans=0; rr char c=getchar();
  10. while (!isdigit(c)) c=getchar();
  11. while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
  12. return ans;
  13. }
  14. inline void print(long long ans){
  15. if (ans>9) print(ans/10);
  16. putchar(ans%10+48);
  17. }
  18. inline void dfs1(int x,int fa){
  19. dep[x]=dep[fa]+1,fat[x]=fa,son[x]=1;
  20. for (rr int i=ls[x],mson=-1;i;i=e[i].next)
  21. if (e[i].y!=fa){
  22. W[e[i].y]=W[x]+e[i].w,dfs1(e[i].y,x),son[x]+=son[e[i].y];
  23. if (son[e[i].y]>mson) big[x]=e[i].y,mson=son[e[i].y];
  24. }
  25. }
  26. inline void dfs2(int x,int linp){
  27. dfn[x]=++tot,nfd[tot]=x,top[x]=linp;
  28. if (!big[x]) return; dfs2(big[x],linp);
  29. for (rr int i=ls[x];i;i=e[i].next)
  30. if (e[i].y!=fat[x]&&e[i].y!=big[x])
  31. dfs2(e[i].y,e[i].y);
  32. }
  33. inline signed Lca(int x,int y){
  34. while (top[x]!=top[y]){
  35. if (dep[top[x]]<dep[top[y]]) x^=y,y^=x,x^=y;
  36. x=fat[top[x]];
  37. }
  38. if (dep[x]>dep[y]) x^=y,y^=x,x^=y;
  39. return x;
  40. }
  41. inline long long doit(int x,int y){
  42. if (x==y) return 0;
  43. return W[x]+W[y]-2*W[Lca(x,y)];
  44. }
  45. signed main(){
  46. n=iut(); rr int Q=iut();
  47. for (rr int i=1;i<n;++i){
  48. rr int x=iut(),y=iut(),w=iut();
  49. e[++k]=(node){y,w,ls[x]},ls[x]=k,
  50. e[++k]=(node){x,w,ls[y]},ls[y]=k;
  51. }
  52. dfs1(1,0),dfs2(1,1);
  53. while (Q--){
  54. rr int x=iut(),lx,rx;
  55. if (!v[x]) uk.insert(dfn[x]);
  56. it=uk.lower_bound(dfn[x]);
  57. if (it!=uk.begin()) --it; else it=--uk.end(); lx=nfd[*it];
  58. it=uk.upper_bound(dfn[x]);
  59. if (it==uk.end()) it=uk.begin(); rx=nfd[*it];
  60. if (v[x]) uk.erase(dfn[x]);
  61. rr long long sw=doit(lx,x)+doit(x,rx)-doit(lx,rx);
  62. if (!v[x]) v[x]=1,ans+=sw;
  63. else v[x]=0,ans-=sw;
  64. print(ans),putchar(10);
  65. }
  66. return 0;
  67. }

#搜索,树剖,set#洛谷 3322 JZOJ 4049 [SDOI2015]排序&洛谷 3320 JZOJ 4050 [SDOI2015]寻宝游戏的更多相关文章

  1. BZOJ 3672 [NOI2014]购票 (凸优化+树剖/树分治)

    题目大意: 略 题面传送门 怎么看也是一道$duliu$题= = 先推式子,设$dp[x]$表示到达$x$点到达1节点的最小花费 设$y$是$x$的一个祖先,则$dp[x]=min(dp[y]+(di ...

  2. 洛谷P4332 [SHOI2014]三叉神经树(LCT,树剖,二分查找,拓扑排序)

    洛谷题目传送门 你谷无题解于是来补一发 随便百度题解,发现了不少诸如树剖\(log^3\)LCT\(log^2\)的可怕描述...... 于是来想想怎么利用题目的性质,把复杂度降下来. 首先,每个点的 ...

  3. 洛谷P3676 小清新数据结构题 【树剖 + BIT】

    题目链接 洛谷P3676 题解 我们先维护\(1\)为根的答案,再考虑换根 一开始的答案可以\(O(n)\)计算出来 考虑修改,记\(s[u]\)表示\(u\)为根的子树的权值和 当\(u\)节点产生 ...

  4. 【树链剖分】洛谷P3384树剖模板

    题目描述 如题,已知一棵包含N个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作: 操作1: 格式: 1 x y z 表示将树从x到y结点最短路径上所有节点的值都加上z 操作2: 格式 ...

  5. 洛谷树剖模板题 P3384 | 树链剖分

    原题链接 对于以u为根的子树,后代节点的dfn显然比他的dfn大,我们可以记录一下回溯到u的dfn,显然这两个dfn构成了一个连续区间,代表u及u的子树 剩下的就和树剖一样了 #include< ...

  6. 洛谷P4719 动态DP —— 动态DP(树剖+矩乘)

    题目:https://www.luogu.org/problemnew/show/P4719 感觉这篇博客写得挺好:https://blog.csdn.net/litble/article/detai ...

  7. 洛谷P4216 [SCOI2015]情报传递(树剖+主席树)

    传送门 我们可以进行离线处理,把每一个情报员的权值设为它开始收集情报的时间 那么设询问的时间为$t$,就是问路径上有多少个情报员的权值小于等于$t-c-1$ 这个只要用主席树上树就可以解决了,顺便用树 ...

  8. 洛谷P4315 月下“毛景树”(树剖+线段树)

    传送门 woc这该死的码农题…… 把每一条边转化为它连接的两点中深度较深的那一个,然后就可以用树剖+线段树对路径进行修改了 然后顺便注意在上面这种转化之后,树剖的时候不能搞$LCA$ 然后是几个注意点 ...

  9. 洛谷P4116 Qtree3(树剖+线段树)

    传送门 LCT秒天秒地 树剖比较裸的题了 用线段树记录一下区间的最左边的黑点的编号(因为同一条链上肯定是最左边的深度最小,到根节点距离最近) 然后记得树剖的时候肯定是越后面的答案越优,因为深度越浅 / ...

  10. 洛谷P3250 [HNOI2016]网络(整体二分+树状数组+树剖)

    传送门 据说正解是树剖套堆???然而代码看着稍微有那么一点点长…… 考虑一下整体二分,设当前二分到的答案为$mid$,如果所有大于$mid$的边都经过当前点$x$,那么此时$x$的答案必定小于等于$m ...

随机推荐

  1. pikachu php反序列化漏洞

    原理 php中serialize(),unserialize()这两个函数. 序列化serialize() 序列化说通俗点就是把一个对象变成可以传输的字符串,比如下面是一个对象: class S{ p ...

  2. MySQL的随机排序(random orderby)

    MySQL的随机排序(random orderby)是指在查询数据库时,将结果集以随机的方式排列.这种排序方式可以用于有趣的应用场景,例如实现随机音乐播放.广告推荐等. 要实现MySQL的随机排序,可 ...

  3. SpringBoot事务注解@Transactional 事物回滚、手动回滚事物

    处理springboot 下提交事务异常,数据库没有回滚的问题. spring的文档中说道,spring声明式事务管理默认对非检查型异常和运行时异常进行事务回滚,而对检查型异常则不进行回滚操作. 什么 ...

  4. 项目实战:Qt+OSG三维2D文字实时效果查看工具

    需求   OSG三维中2D文字的基本属性较多,方便实时查看效果,并出对应文本代码.   Demo      工具下载地址   CSDN免积分下载地址:https://download.csdn.net ...

  5. 【LeetCode剑指offer#06】实现pow函数、计算x的平方根

    实现pow函数 实现 pow(x, n) ,即计算 x 的整数 n 次幂函数(即,xn ). 示例 1: 输入:x = 2.00000, n = 10 输出:1024.00000 示例 2: 输入:x ...

  6. 【Azure 存储服务】Azure Data Lake Storage (ADLS) Gen2 GRS Failover是否支持自动切换或者手动切换到灾备的终结点呢?

    问题描述 在Azure的存储服务中,介绍灾备恢复和Storage Account故障转移的文档中,有一句话"Account failover is not supported for sto ...

  7. 【Azure 事件中心】使用Kafka消费Azure EventHub中数据,遇见消费慢的情况可以如何来调节呢?

    问题描述 使用Kafka消费Azure EventHub中数据,遇见消费慢的情况可以如何来调节呢? 问题解答 查看Kafka Consumer的配置参数,其中最只要的一个参数为:max.poll.re ...

  8. 【Azure Developer】使用 Azure VM 上的用户分配托管标识访问 Azure Key Vault 中国区代码示例

    问题描述 在Global版本的Azure Key Vault 文档中,有一节介绍在Azure VM中使用标识获取访问令牌,调用Key Vault中的资源.但是在示例中,只有curl的命令执行,而没有代 ...

  9. 使用@RequestBody注解踩的坑

    一.问题由来 最近在和前端调试一个自己写的接口时,频频出现问题,让我很是烦恼.因此写下这篇博文来记录开发中遇到的一些问题.第一个问题是 前端页面传递参数后,后台不能正常接收参数.我写好接口以后,通过s ...

  10. ContextMenuManager右键z 右键菜单

    常用软件 下载 https://files.cnblogs.com/files/pengchenggang/ContextMenuManager右键z-右键菜单.rar?t=1664158084