zoukankan      html  css  js  c++  java
  • 1563: [NOI2009]诗人小G

    1563: [NOI2009]诗人小G

    https://lydsy.com/JudgeOnline/problem.php?id=1563

    分析:

      直接转移f[i]=f[j]+cost(i,j),cost(i,j)=(sum[i]-sum[j])p

      然后有决策单调性,就可以二分+队列了。注意两个字符串之间还有一个空格,所以长度+1,很多字符串合起来后,总的长度还要-1,最后一个没空格。

      证明?byvoid

      luogu输出方案,加上后一直过不了,g,nxt数组是输出方案的部分

    代码:

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cstring>
     4 #include<cmath>
     5 #include<iostream>
     6 #include<cctype>
     7 #include<set>
     8 #include<vector>
     9 #include<queue>
    10 #include<map>
    11 #define fi(s) freopen(s,"r",stdin);
    12 #define fo(s) freopen(s,"w",stdout);
    13 using namespace std;
    14 typedef long long LL;
    15 typedef long double LD;
    16  
    17 inline int read() {
    18     int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
    19     for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f;
    20 }
    21  
    22 const int N = 100005;
    23 const LL INF = 1e18;
    24  
    25 char str[N][32], pr[25];
    26 int len[N], g[N], nxt[N];
    27 LD f[N];
    28 LL sum[N];
    29 int n, Len, P;
    30 struct Node{
    31     int p, l, r;
    32     Node() {}
    33     Node(int _,int __,int ___) { p = _, l = __, r = ___; }
    34 }q[N];
    35  
    36 LD ksm(LD x) {
    37     LD ans = 1; int b = P;
    38     while (b) {
    39         if (b & 1) ans = ans * x;
    40         x = x * x;
    41         b >>= 1;
    42     }
    43     return ans;
    44 }
    45 void init() {
    46     n = read(), Len = read(), P = read();
    47     for (int i=1; i<=n; ++i) {
    48         scanf("%s", str[i] + 1); 
    49         sum[i] = sum[i - 1] + (len[i] = strlen(str[i] + 1) + 1); 
    50     }
    51 }
    52 LD Calc(int i,int j) {
    53     return f[j] + ksm(abs(sum[i] - sum[j] - Len - 1));
    54 }
    55 int binary_search(int l,int r,int x,int y) {
    56     int ans = n;
    57     while (l <= r) {
    58         int mid = (l + r) >> 1;
    59         if (Calc(mid, x) < Calc(mid, y)) ans = mid, r = mid - 1;
    60         else l = mid + 1;
    61     }
    62     return ans;
    63 }
    64 void solve() {
    65     int L = 1, R = 0;
    66     q[++R] = Node(0, 1, n);
    67     for (int i=1; i<=n; ++i) {
    68         while (L <= R && q[L].r < i) L ++;
    69         int j = q[L].p; 
    70         f[i] = Calc(i, j); 
    71         g[i] = j;
    72         if (Calc(n, q[R].p) < Calc(n, i)) continue; // 如果最后一个点从i转移不优,那么说明i没有覆盖的区间,不需要二分了
    73         while (L <= R && Calc(q[R].l, q[R].p) > Calc(q[R].l, i)) R --;
    74         q[R].r = binary_search(q[R].l, n, i, q[R].p) - 1;
    75         q[++R] = Node(i, q[R - 1].r + 1, n);
    76     }
    77 }
    78 void print() {
    79       if (f[n] > INF) puts("Too hard to arrange");
    80     else printf("%lld
    ", (LL)(f[n]));
    81     puts(pr);
    82 }
    83 int main() {
    84     strcpy(pr, "--------------------");
    85     int T = read();
    86     while (T--) {
    87         init(); 
    88         solve();
    89         print();
    90     }
    91     return 0;
    92 }
  • 相关阅读:
    支付宝支付
    七牛云存储介绍
    ubuntu开发机初始化
    Unity3D 正六边形,环状扩散,紧密分布,的程序
    Unity属性的封装、继承、方法隐藏
    DateTime.Now的一些用法
    [转] 增强现实 colAR Mix 浅析
    [转] Vuforia AR 中的阴影与浮现效果
    网址整理
    [转] 如何使用unity Vs来进行断点调试
  • 原文地址:https://www.cnblogs.com/mjtcn/p/9774761.html
Copyright © 2011-2022 走看看