zoukankan      html  css  js  c++  java
  • [P5665][CSP2019D2T2] 划分

    先说说部分分做法吧

    1.(n leq 10) 指数级瞎草都可以2333

    2.(n leq 50) 好像并没有什么做法…也许给剪枝的人部分分吧

    3.(n leq 400) 这个复杂度是给 (O(n^3)) 过的… 大概就是 考虑一个数组 (dp_{n,n}) 每次枚举转移点(i , j ,k)

    [dp_{j,k} = min{ dp_{i,j} + (sum_k - sum_j)^2} ]

    4.(n leq 5000)

    这道题有个显而易见的结论:最后一段尽量小 答案会最优…

    所以每次考虑转移能转移的 最小的直接二分就行了吧…这样就少掉一维空间 时间也变成 (O(n^2 log n))
    不过仔细想想好像 (n^2)就行了

    1. 正解吧…… 这个题的大毒瘤出题人出的题要用高精度 顺手还卡了内存… 好像把zyy和hy等一堆神仙卡掉了…

    由于是单调的 所以单调队列维护一个 ( ext{d(i)}) 即以 (i) 结尾的这一段的值…

    所以维护一个单调队列 然后注意一点 记录每个点的前驱(pre_i) 最后统计答案 这样才能保证int128空间不会爆炸
    前排赠送 ( exttt{88pts}) 代码

    ( exttt{code})

    #include<bits/stdc++.h>
    #define int long long
    using namespace std ;
    const int N = 4e7 + 10 ;
    int n , type , a[N] , q[N] , dp[N] , sum[N] , d[N] ;
    signed main() {
      ios :: sync_with_stdio(false) ; cin.tie(nullptr) ; cout.tie(nullptr) ;
      cin >> n >> type ;
      for(register int i = 1 ; i <= n ; i ++) { cin >> a[i] ; sum[i] = sum[i - 1] + a[i] ; }
      int h , t ; q[h = t = 0] = 0 ;
      for(register int i = 1 ; i <= n ; i ++) {
        while(h < t && d[q[h + 1]] + sum[q[h + 1]] <= sum[i]) ++ h ;
        d[i] = sum[i] - sum[q[h]] ; dp[i] = dp[q[h]] + (d[i] * d[i]) ;
        while(h < t && d[q[t]] + sum[q[t]] >= d[i] + sum[i]) -- t ;
        q[++ t] = i ;
      }
      cout << dp[n] << '
    ' ;
      return 0 ;
    }
    

    至于高精懒得写… 直接拿int128水了 然后把dp数组类型改成int128 和原来的分数莫得区别2333
    直接转移竟然( exttt{1G}) 内存都不够用 佛了…

    ( exttt{code})

    #include<bits/stdc++.h>
    using namespace std ;
    const int N = 4e7 + 10 ;
    const int M = 1e5 + 10 ;
    const int mod = (1 << 30) ;
    int n , type , x , y , z , m ;
    int a[N] , b[N] , p[M] , l[M] , r[M] , q[N] , pre[N] ;
    long long sum[N] ;
    inline long long d(int x) { return sum[x] - sum[pre[x]] ; }
    signed main() {
      ios :: sync_with_stdio(false) ; cin.tie(nullptr) ; cout.tie(nullptr) ;
      cin >> n >> type ;
      if(type) {
    		cin >> x >> y >> z >> b[1] >> b[2] >> m ;
        for(register int i = 1 ; i <= m ; i ++) { cin >> p[i] >> l[i] >> r[i] ; }
        for(register int i = 3 ; i <= n ; i ++) { b[i] = (0ll + 1ll * b[i - 1] * x + 1ll * b[i - 2] * y + z) % mod ; }
        for(register int i = 1 ; i <= m ; i ++)
          for(register int j = p[i - 1] + 1 ; j <= p[i] ; j ++) { a[j] = (b[j] % (r[i] - l[i] + 1)) + l[i] ; sum[j] = sum[j - 1] + a[j] ; }
    	}
      else {
      	for(register int i = 1 ; i <= n ; i ++) { cin >> a[i] ; sum[i] = sum[i - 1] + a[i] ; }
    	} int h , t ; q[h = t = 0] = 0 ;
      for(register int i = 1 ; i <= n ; i ++) {
        while(h < t && d(q[h + 1]) + sum[q[h + 1]] <= sum[i]) ++ h ; 
    		pre[i] = q[h] ;
        while(h < t && d(q[t]) + sum[q[t]] >= d(i) + sum[i]) -- t ;
        q[++ t] = i ;
      }  int now = n ; __int128 ans = 0 , tmp = 1 ;
    	while(now) { tmp = d(now) ; tmp *= d(now) ; ans += tmp ; now = pre[now] ; }
    	int st[50] , tp = 0 ;
    	while(ans) { st[++ tp] = ans % 10 ; ans /= 10 ; }
    	while(tp) { cout << st[tp --] ; }
      return 0 ;
    }
    

    别喷int128啊

  • 相关阅读:
    spring-boot-route(七)整合jdbcTemplate操作数据库
    spring-boot-route(六)整合JApiDocs生成接口文档
    spring-boot-route(五)整合Swagger生成接口文档
    spring-boot-route(四)全局异常处理
    spring-boot-route(三)实现多文件上传
    spring-boot-route(二)读取配置文件的几种方式
    spring-boot-route(一)Controller接收参数的几种方式
    国庆,要干几件大事
    栈与队列简介
    一文了解Zookeeper
  • 原文地址:https://www.cnblogs.com/Isaunoya/p/11890572.html
Copyright © 2011-2022 走看看