• C - Bricks and Bags,E - Hanging Hearts,H-Leonard的子序列_树状数组优化dp,B - Hash 河南省赛


    14天阅读挑战赛

    C - Bricks and Bags

    情况考虑少了,以为把最大值和最小值单独放在两个包里是最优的,其实不是,应该是分别枚举i,分别和最大值或最小值单独放在两个包里,然后去更新答案

    1. #include
    2. #define int long long
    3. #define endl '\n'
    4. #define For(i,a,b) for(i=(a);i<=(b);++i)
    5. #define ios (ios::sync_with_stdio(false),cin.tie(0),cout.tie(0))
    6. using namespace std;
    7. const int N=2e6+5;
    8. const int inf=1e18;
    9. const int mod=998244353;
    10. int n,a[N];
    11. void solve()
    12. {
    13. cin>>n;
    14. for(int i=1;i<=n;i++)
    15. cin>>a[i];
    16. sort(a+1,a+n+1);
    17. int ans=max(a[n]-a[1]+a[2]-a[1],a[n]-a[1]+a[n]-a[n-1]);
    18. for(int i=2;i<=n-2;i++)
    19. ans=max(ans,a[i+1]-a[i]+a[n]-a[i]);
    20. for(int i=3;i<=n-1;i++)
    21. ans=max(ans,a[i]-a[i-1]+a[i]-a[1]);
    22. cout<
    23. }
    24. signed main()
    25. {
    26. //ios;
    27. int T;cin>>T;
    28. while(T--)
    29. solve();
    30. return 0;
    31. }

    E - Hanging Hearts

    父节点最后的值一定是子树中最小的值,删的时候可以删一条链,也可以先把子树删完再去删子树的根节点,但这样的话子树的根节点就没有贡献了,因为他是子树的最小值,f[u][0/1]表示以u为根节点的子树删子树或者删链所能获得的最大长度

    Codeforces Round #831 (Div. 1 + Div. 2) - 知乎 (zhihu.com)

    1. #include
    2. #define int long long
    3. #define endl '\n'
    4. using namespace std;
    5. const int N=2e6+100;
    6. int n,f[N][2];
    7. vector<int>v[N];
    8. void dfs(int u)
    9. {
    10. if(v[u].size()==0)
    11. {
    12. f[u][0]=f[u][1]=1;return;
    13. }
    14. for(auto j:v[u])
    15. {
    16. dfs(j);
    17. f[u][1]=max(f[u][1],f[j][1]+1);
    18. f[u][0]+=max(f[j][0],f[j][1]);
    19. }
    20. }
    21. signed main()
    22. {
    23. cin>>n;
    24. for(int i=2;i<=n;i++)
    25. {
    26. int x;cin>>x;
    27. v[x].push_back(i);
    28. }
    29. dfs(1);
    30. cout<<max(f[1][0],f[1][1]);
    31. return 0;
    32. }

    H-Leonard的子序列_树状数组优化dp

    设状态f[i]表示以a[i]为结尾的子序列长度和,那么f[i]=sum(f[j],j

    1. #include
    2. #define int long long
    3. #define lowbit(x) ((-x)&(x))
    4. #define endl '\n'
    5. using namespace std;
    6. const int N=2e6+100;
    7. const int mod=1e9+7;
    8. int n,t[N],t2[N],a[N],b[N],dp[N],f[N];
    9. void add(int x,int y)
    10. {
    11. for(int i=x;i<=n;i+=lowbit(i))
    12. t[i]=(t[i]+y)%mod;
    13. }
    14. void add2(int x,int y)
    15. {
    16. for(int i=x;i<=n;i+=lowbit(i))
    17. t2[i]=(t2[i]+y)%mod;
    18. }
    19. int ask(int x)
    20. {
    21. int res=0;
    22. for(int i=x;i;i-=lowbit(i))
    23. res=(res+t[i])%mod;
    24. return res;
    25. }
    26. int ask2(int x)
    27. {
    28. int res=0;
    29. for(int i=x;i;i-=lowbit(i))
    30. res=(res+t2[i])%mod;
    31. return res;
    32. }
    33. signed main()
    34. {
    35. cin>>n;
    36. for(int i=1;i<=n;i++) cin>>a[i],b[i]=a[i];
    37. sort(b+1,b+n+1);
    38. int m=unique(b+1,b+n+1)-b-1;
    39. int ans=0;
    40. for(int i=1;i<=n;i++)
    41. {
    42. int id=lower_bound(b+1,b+m+1,a[i]/2LL)-b;
    43. if(b[id]>a[i]/2LL) id--;
    44. int len=ask(id),len2=ask2(id);
    45. dp[i]=1;f[i]=1;
    46. dp[i]=(dp[i]+len)%mod;
    47. f[i]=((f[i]+len2)%mod+len)%mod;
    48. id=lower_bound(b+1,b+m+1,a[i])-b;
    49. add(id,dp[i]);
    50. add2(id,f[i]);
    51. }
    52. for(int i=1;i<=n;i++)
    53. ans=(ans+f[i])%mod;
    54. cout<
    55. return 0;
    56. }

    B - Hash 河南省赛

    经过证明可以得出子串的大小不超过15,超过16的话就不优了,感性的理解一下,我们一定是想要哈希的值不超过mod最好,因为超过了就有浪费的,而且31的次方上升的很快,所以尽可能地让子段的哈希值靠近但不超过mod是最优的,下面是题解的证明

    然后dp[i]表示以i这个字母为结尾的子串所能获得的最大价值,那么dp[i]=max(dp[i],dp[j]+hash(j+1,i)),然后枚举更新答案就可以了

    【CCPC】2022河南省赛补题记录-BI - 掘金 (juejin.cn)

     

    1. #include
    2. #define int long long
    3. #define lowbit(x) ((-x)&(x))
    4. #define endl '\n'
    5. using namespace std;
    6. const int N=2e6+100;
    7. const int mod=998244353;
    8. const int base=31;
    9. int dp[N],n,po[N],h[N];
    10. char s[N];
    11. map<char,int>mp;
    12. int geth(int l,int r)
    13. {
    14. return ((h[r]-h[l-1]*po[r-l+1]%mod)%mod+mod)%mod;
    15. }
    16. signed main()
    17. {
    18. cin>>(s+1);
    19. mp['a']=1;mp['e']=2;mp['h']=3;mp['n']=4;
    20. n=strlen(s+1);
    21. po[0]=1;
    22. for(int i=1;i<=2*n;i++) po[i]=po[i-1]*base%mod;
    23. for(int i=n+1;i<=2*n;i++) s[i]=s[i-n];
    24. h[0]=0;
    25. for(int i=1;i<=2*n;i++) h[i]=(h[i-1]*base%mod+mp[s[i]])%mod;
    26. dp[0]=0;
    27. int ans=0;
    28. for(int k=1;k<=min(16LL,n);k++)
    29. {
    30. for(int i=1;i<=2*n;i++) dp[i]=0;
    31. for(int i=k;i<=k+n-1;i++)
    32. {
    33. for(int j=max(i-16LL,k-1LL);j<=i-1;j++)
    34. {
    35. dp[i]=max(dp[i],dp[j]+geth(j+1,i));
    36. // cout<<"dp[i]="<
      }
    37. }
    38. ans=max(ans,dp[k+n-1]);
    39. }
    40. cout<
    41. return 0;
    42. }

    #144. DFS 序 1 - 题目 - LibreOJ (loj.ac) 树上问题转化成区间问题

    处理出dfs序之后发现子树都是一段一段的,这就可以转化成区间问题,然后就是树状数组的板子了

    DFS 序入门 - Planet6174 的博客 - 洛谷博客 (luogu.com.cn) 

    1. #include
    2. #define int long long
    3. #define lowbit(x) ((-x)&(x))
    4. #define endl '\n'
    5. using namespace std;
    6. const int N=2e6+100;
    7. const int mod=998244353;
    8. int head[N],cnt;
    9. struct Edge
    10. {
    11. int next,to;
    12. }e[N];
    13. void addedge(int from,int to)
    14. {
    15. e[++cnt].next=head[from];
    16. e[cnt].to=to;
    17. head[from]=cnt;
    18. }
    19. int num,n,m,rt,t[N],dfn[N],a[N];
    20. void add(int x,int y)
    21. {
    22. for(int i=x;i<=n;i+=lowbit(i))
    23. t[i]+=y;
    24. }
    25. int ask(int x)
    26. {
    27. int res=0;
    28. for(int i=x;i;i-=lowbit(i))
    29. res+=t[i];
    30. return res;
    31. }
    32. struct node
    33. {
    34. int l,r;
    35. }p[N];
    36. void dfs(int u,int fa)
    37. {
    38. num++;
    39. dfn[u]=num;
    40. p[u].l=num;
    41. for(int i=head[u];i;i=e[i].next)
    42. {
    43. int j=e[i].to;
    44. if(j==fa) continue;
    45. dfs(j,u);
    46. }
    47. p[u].r=num;
    48. }
    49. signed main()
    50. {
    51. ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    52. cin>>n>>m>>rt;
    53. for(int i=1;i<=n;i++) cin>>a[i];
    54. for(int i=1;i
    55. {
    56. int u,v;
    57. cin>>u>>v;
    58. addedge(u,v);
    59. addedge(v,u);
    60. }
    61. dfs(rt,0);
    62. for(int i=1;i<=n;i++) add(dfn[i],a[i]);
    63. // for(int i=1;i<=n;i++)
    64. // {
    65. // cout<
    66. // }
    67. while(m--)
    68. {
    69. int x,y,op;cin>>op;
    70. if(op==1)
    71. {
    72. cin>>x>>y;
    73. add(dfn[x],y);
    74. }
    75. else
    76. {
    77. cin>>x;
    78. int ans=ask(p[x].r)-ask(p[x].l-1);
    79. cout<
    80. }
    81. }
    82. return 0;
    83. }

  • 相关阅读:
    【获取当前月时间】elementul日期选择器在页面一进来直接获取到本月1号到当前日期的方法【详细注释】
    前端练习--W3C导航条
    2022宁夏杯B题论文分析+完整代码(大学生就业问题分析)
    最小系统板 STM32入门,呼吸灯实现(STM32F103C6T6)
    多目标跟踪算法方案总结
    【附源码】计算机毕业设计SSM蔬果批发网络平台
    C++入门知识——构造函数初始化列表、static与友元
    Appium移动自动化测试--安装Appium
    article-机翼简易模型结构静力学分析与预应力模态分析
    【Java开发工具】下载安装eclipse并汉化配置教程(所以操作系统通用)
  • 原文地址:https://blog.csdn.net/weixin_52621204/article/details/127603286