Submission #3674364


Source Code Expand

import std.stdio;
import std.string;
import std.format;
import std.conv;
import std.typecons;
import std.algorithm;
import std.functional;
import std.bigint;
import std.numeric;
import std.array;
import std.math;
import std.range;
import std.container;
import std.concurrency;
import std.traits;
import std.uni;
import core.bitop : popcnt;
alias Generator = std.concurrency.Generator;

enum long INF = long.max/3;
enum long MOD = 10L^^9+7;

class P {
  long a, b;
  bool used = false;
  bool beginning = false;
  bool ending = false;
}

void main() {
  long N, K;
  scanln(N, K);

  P[] ps;

  {
    P[] qs = N.rep!(() => new P);
    long[] next = new long[N+1];
    {
      long[] as = readln.split.to!(long[]).array;
      long[] bs = readln.split.to!(long[]).array;
      foreach(i; 0..N) {
        qs[i].a = as[i];
        qs[i].b = bs[i];
        next[as[i]] = i;
      }
    }

    foreach(i, p; qs) {
      if (p.used) continue;
      p.beginning = true;
      P q = p;
      while(q.b != p.a) {
        q.used = true;
        ps ~= q;
        q = qs[next[q.b]];
      }
      q.used = true;
      q.ending = true;
      ps ~= q;
    }
  }

  long[][][] dp = new long[][][](2, N+1, 4);
  foreach(i; 0..2) foreach(j; 0..N+1) {
      dp[i][j][] = -INF;
  }
  dp[0][0][0] = 0;

  foreach(i, p; ps) {
    foreach(j; 0..i+1+1) {
      dp[(i+1)%2][j][] = -INF;
    }
    foreach(j; 0..i+1+1) {
      if (p.beginning) {
        foreach(k; 0..2) foreach(l; 0..2) {
          if (j>0) dp[(i+1)%2][j][1|0<<1].ch!max(dp[i%2][j-1][k|l<<1] + p.a);
          if (j>0) dp[(i+1)%2][j][0|1<<1].ch!max(dp[i%2][j-1][k|l<<1] + p.b);
        }
      } else if (p.ending) {
        if (j>0) dp[(i+1)%2][j][0|0<<1].ch!max(dp[i%2][j-1][0|0<<1] + p.a);
                 dp[(i+1)%2][j][0|0<<1].ch!max(dp[i%2][j][0|1<<1] + p.a);
        if (j>0) dp[(i+1)%2][j][0|1<<1].ch!max(dp[i%2][j-1][0|0<<1] + p.b);
        if (j>0) dp[(i+1)%2][j][0|1<<1].ch!max(dp[i%2][j-1][0|1<<1] + p.b);

        if (j>0) dp[(i+1)%2][j][1|0<<1].ch!max(dp[i%2][j-1][1|0<<1] + p.a);
                 dp[(i+1)%2][j][1|0<<1].ch!max(dp[i%2][j][1|1<<1] + p.a);
                 dp[(i+1)%2][j][1|1<<1].ch!max(dp[i%2][j][1|0<<1] + p.b);
                 dp[(i+1)%2][j][1|1<<1].ch!max(dp[i%2][j][1|1<<1] + p.b);
      } else {
        foreach(k; 0..2) {
          if (j>0) dp[(i+1)%2][j][k|0<<1].ch!max(dp[i%2][j-1][k|0<<1] + p.a);
                   dp[(i+1)%2][j][k|0<<1].ch!max(dp[i%2][j][k|1<<1] + p.a);
          if (j>0) dp[(i+1)%2][j][k|1<<1].ch!max(dp[i%2][j-1][k|0<<1] + p.b);
          if (j>0) dp[(i+1)%2][j][k|1<<1].ch!max(dp[i%2][j-1][k|1<<1] + p.b);
        }
      }
    }
  }

  dp[N%2][K..$].join.reduce!max.writeln;
}

// ----------------------------------------------


void times(alias fun)(long n) {
  // n.iota.each!(i => fun());
  foreach(i; 0..n) fun();
}
auto rep(alias fun, T = typeof(fun()))(long n) {
  // return n.iota.map!(i => fun()).array;
  T[] res = new T[n];
  foreach(ref e; res) e = fun();
  return res;
}

T ceil(T)(T x, T y) if (isIntegral!T || is(T == BigInt)) {
  // `(x+y-1)/y` will only work for positive numbers ...
  T t = x / y;
  if (t * y < x) t++;
  return t;
}

T floor(T)(T x, T y) if (isIntegral!T || is(T == BigInt)) {
  T t = x / y;
  if (t * y > x) t--;
  return t;
}

ref T ch(alias fun, T, S...)(ref T lhs, S rhs) {
  return lhs = fun(lhs, rhs);
}
unittest {
  long x = 1000;
  x.ch!min(2000);
  assert(x == 1000);
  x.ch!min(3, 2, 1);
  assert(x == 1);
  x.ch!max(100).ch!min(1000); // clamp
  assert(x == 100);
  x.ch!max(0).ch!min(10); // clamp
  assert(x == 10);
}

mixin template Constructor() {
  import std.traits : FieldNameTuple;
  this(Args...)(Args args) {
    // static foreach(i, v; args) {
    foreach(i, v; args) {
      mixin("this." ~ FieldNameTuple!(typeof(this))[i]) = v;
    }
  }
}

void scanln(Args...)(auto ref Args args) {
  import std.meta;
  template getFormat(T) {
    static if (isIntegral!T) {
      enum getFormat = "%d";
    } else static if (isFloatingPoint!T) {
      enum getFormat = "%g";
    } else static if (isSomeString!T || isSomeChar!T) {
      enum getFormat = "%s";
    } else {
      static assert(false);
    }
  }
  enum string fmt = [staticMap!(getFormat, Args)].join(" ");
  string[] inputs = readln.chomp.split;
  foreach(i, ref v; args) {
    v = inputs[i].to!(Args[i]);
  }
}

// fold was added in D 2.071.0
static if (__VERSION__ < 2071) {
  template fold(fun...) if (fun.length >= 1) {
    auto fold(R, S...)(R r, S seed) {
      static if (S.length < 2) {
        return reduce!fun(seed, r);
      } else {
        return reduce!fun(tuple(seed), r);
      }
    }
  }
}

// cumulativeFold was added in D 2.072.0
static if (__VERSION__ < 2072) {
  template cumulativeFold(fun...)
  if (fun.length >= 1)
  {
    import std.meta : staticMap;
    private alias binfuns = staticMap!(binaryFun, fun);

    auto cumulativeFold(R)(R range)
    if (isInputRange!(Unqual!R))
    {
      return cumulativeFoldImpl(range);
    }

    auto cumulativeFold(R, S)(R range, S seed)
    if (isInputRange!(Unqual!R))
    {
      static if (fun.length == 1)
        return cumulativeFoldImpl(range, seed);
      else
        return cumulativeFoldImpl(range, seed.expand);
    }

    private auto cumulativeFoldImpl(R, Args...)(R range, ref Args args)
    {
      import std.algorithm.internal : algoFormat;

      static assert(Args.length == 0 || Args.length == fun.length,
        algoFormat("Seed %s does not have the correct amount of fields (should be %s)",
          Args.stringof, fun.length));

      static if (args.length)
        alias State = staticMap!(Unqual, Args);
      else
        alias State = staticMap!(ReduceSeedType!(ElementType!R), binfuns);

      foreach (i, f; binfuns)
      {
        static assert(!__traits(compiles, f(args[i], e)) || __traits(compiles,
            { args[i] = f(args[i], e); }()),
          algoFormat("Incompatible function/seed/element: %s/%s/%s",
            fullyQualifiedName!f, Args[i].stringof, E.stringof));
      }

      static struct Result
      {
      private:
        R source;
        State state;

        this(R range, ref Args args)
        {
          source = range;
          if (source.empty)
            return;

          foreach (i, f; binfuns)
          {
            static if (args.length)
              state[i] = f(args[i], source.front);
            else
              state[i] = source.front;
          }
        }

      public:
        @property bool empty()
        {
          return source.empty;
        }

        @property auto front()
        {
          assert(!empty, "Attempting to fetch the front of an empty cumulativeFold.");
          static if (fun.length > 1)
          {
            import std.typecons : tuple;
            return tuple(state);
          }
          else
          {
            return state[0];
          }
        }

        void popFront()
        {
          assert(!empty, "Attempting to popFront an empty cumulativeFold.");
          source.popFront;

          if (source.empty)
            return;

          foreach (i, f; binfuns)
            state[i] = f(state[i], source.front);
        }

        static if (isForwardRange!R)
        {
          @property auto save()
          {
            auto result = this;
            result.source = source.save;
            return result;
          }
        }

        static if (hasLength!R)
        {
          @property size_t length()
          {
            return source.length;
          }
        }
      }

      return Result(range, args);
    }
  }
}

// minElement/maxElement was added in D 2.072.0
static if (__VERSION__ < 2072) {
  private auto extremum(alias map, alias selector = "a < b", Range)(Range r)
  if (isInputRange!Range && !isInfinite!Range &&
    is(typeof(unaryFun!map(ElementType!(Range).init))))
  in
  {
    assert(!r.empty, "r is an empty range");
  }
  body
  {
    alias Element = ElementType!Range;
    Unqual!Element seed = r.front;
    r.popFront();
    return extremum!(map, selector)(r, seed);
  }

  private auto extremum(alias map, alias selector = "a < b", Range,
              RangeElementType = ElementType!Range)
             (Range r, RangeElementType seedElement)
  if (isInputRange!Range && !isInfinite!Range &&
    !is(CommonType!(ElementType!Range, RangeElementType) == void) &&
     is(typeof(unaryFun!map(ElementType!(Range).init))))
  {
    alias mapFun = unaryFun!map;
    alias selectorFun = binaryFun!selector;

    alias Element = ElementType!Range;
    alias CommonElement = CommonType!(Element, RangeElementType);
    Unqual!CommonElement extremeElement = seedElement;

    alias MapType = Unqual!(typeof(mapFun(CommonElement.init)));
    MapType extremeElementMapped = mapFun(extremeElement);

    // direct access via a random access range is faster
    static if (isRandomAccessRange!Range)
    {
      foreach (const i; 0 .. r.length)
      {
        MapType mapElement = mapFun(r[i]);
        if (selectorFun(mapElement, extremeElementMapped))
        {
          extremeElement = r[i];
          extremeElementMapped = mapElement;
        }
      }
    }
    else
    {
      while (!r.empty)
      {
        MapType mapElement = mapFun(r.front);
        if (selectorFun(mapElement, extremeElementMapped))
        {
          extremeElement = r.front;
          extremeElementMapped = mapElement;
        }
        r.popFront();
      }
    }
    return extremeElement;
  }
  private auto extremum(alias selector = "a < b", Range)(Range r)
    if (isInputRange!Range && !isInfinite!Range &&
      !is(typeof(unaryFun!selector(ElementType!(Range).init))))
  {
    alias Element = ElementType!Range;
    Unqual!Element seed = r.front;
    r.popFront();
    return extremum!selector(r, seed);
  }
  private auto extremum(alias selector = "a < b", Range,
              RangeElementType = ElementType!Range)
             (Range r, RangeElementType seedElement)
    if (isInputRange!Range && !isInfinite!Range &&
      !is(CommonType!(ElementType!Range, RangeElementType) == void) &&
      !is(typeof(unaryFun!selector(ElementType!(Range).init))))
  {
    alias Element = ElementType!Range;
    alias CommonElement = CommonType!(Element, RangeElementType);
    Unqual!CommonElement extremeElement = seedElement;
    alias selectorFun = binaryFun!selector;

    // direct access via a random access range is faster
    static if (isRandomAccessRange!Range)
    {
      foreach (const i; 0 .. r.length)
      {
        if (selectorFun(r[i], extremeElement))
        {
          extremeElement = r[i];
        }
      }
    }
    else
    {
      while (!r.empty)
      {
        if (selectorFun(r.front, extremeElement))
        {
          extremeElement = r.front;
        }
        r.popFront();
      }
    }
    return extremeElement;
  }
  auto minElement(Range)(Range r)
    if (isInputRange!Range && !isInfinite!Range)
  {
    return extremum(r);
  }
  auto minElement(alias map, Range, RangeElementType = ElementType!Range)
           (Range r, RangeElementType seed)
  if (isInputRange!Range && !isInfinite!Range &&
    !is(CommonType!(ElementType!Range, RangeElementType) == void))
  {
    return extremum!map(r, seed);
  }
  auto minElement(Range, RangeElementType = ElementType!Range)
           (Range r, RangeElementType seed)
    if (isInputRange!Range && !isInfinite!Range &&
      !is(CommonType!(ElementType!Range, RangeElementType) == void))
  {
    return extremum(r, seed);
  }
  auto maxElement(alias map, Range)(Range r)
  if (isInputRange!Range && !isInfinite!Range)
  {
    return extremum!(map, "a > b")(r);
  }
  auto maxElement(Range)(Range r)
  if (isInputRange!Range && !isInfinite!Range)
  {
    return extremum!`a > b`(r);
  }
  auto maxElement(alias map, Range, RangeElementType = ElementType!Range)
           (Range r, RangeElementType seed)
  if (isInputRange!Range && !isInfinite!Range &&
    !is(CommonType!(ElementType!Range, RangeElementType) == void))
  {
    return extremum!(map, "a > b")(r, seed);
  }
  auto maxElement(Range, RangeElementType = ElementType!Range)
           (Range r, RangeElementType seed)
  if (isInputRange!Range && !isInfinite!Range &&
    !is(CommonType!(ElementType!Range, RangeElementType) == void))
  {
    return extremum!`a > b`(r, seed);
  }
}

// popcnt with ulongs was added in D 2.071.0
static if (__VERSION__ < 2071) {
  ulong popcnt(ulong x) {
    x = (x & 0x5555555555555555L) + (x>> 1 & 0x5555555555555555L);
    x = (x & 0x3333333333333333L) + (x>> 2 & 0x3333333333333333L);
    x = (x & 0x0f0f0f0f0f0f0f0fL) + (x>> 4 & 0x0f0f0f0f0f0f0f0fL);
    x = (x & 0x00ff00ff00ff00ffL) + (x>> 8 & 0x00ff00ff00ff00ffL);
    x = (x & 0x0000ffff0000ffffL) + (x>>16 & 0x0000ffff0000ffffL);
    x = (x & 0x00000000ffffffffL) + (x>>32 & 0x00000000ffffffffL);
    return x;
  }
}

Submission Info

Submission Time
Task G - Sum of Cards
User arkark
Language D (DMD64 v2.070.1)
Score 500
Code Size 13287 Byte
Status AC
Exec Time 346 ms
Memory 3836 KB

Judge Result

Set Name Sample All
Score / Max Score 0 / 0 500 / 500
Status
AC × 3
AC × 43
Set Name Test Cases
Sample s1.txt, s2.txt, s3.txt
All 01.txt, 02.txt, 03.txt, 04.txt, 05.txt, 06.txt, 07.txt, 08.txt, 09.txt, 10.txt, 11.txt, 12.txt, 13.txt, 14.txt, 15.txt, 16.txt, 17.txt, 18.txt, 19.txt, 20.txt, 21.txt, 22.txt, 23.txt, 24.txt, 25.txt, 26.txt, 27.txt, 28.txt, 29.txt, 30.txt, 31.txt, 32.txt, 33.txt, 34.txt, 35.txt, 36.txt, 37.txt, 38.txt, 39.txt, 40.txt, s1.txt, s2.txt, s3.txt
Case Name Status Exec Time Memory
01.txt AC 1 ms 256 KB
02.txt AC 1 ms 256 KB
03.txt AC 1 ms 256 KB
04.txt AC 1 ms 256 KB
05.txt AC 1 ms 256 KB
06.txt AC 2 ms 380 KB
07.txt AC 2 ms 380 KB
08.txt AC 3 ms 380 KB
09.txt AC 2 ms 380 KB
10.txt AC 2 ms 380 KB
11.txt AC 2 ms 380 KB
12.txt AC 2 ms 380 KB
13.txt AC 2 ms 380 KB
14.txt AC 2 ms 380 KB
15.txt AC 2 ms 380 KB
16.txt AC 246 ms 3452 KB
17.txt AC 237 ms 3452 KB
18.txt AC 274 ms 1788 KB
19.txt AC 270 ms 1788 KB
20.txt AC 331 ms 1916 KB
21.txt AC 261 ms 3836 KB
22.txt AC 254 ms 3708 KB
23.txt AC 330 ms 2044 KB
24.txt AC 238 ms 1788 KB
25.txt AC 265 ms 3196 KB
26.txt AC 307 ms 3836 KB
27.txt AC 312 ms 1916 KB
28.txt AC 247 ms 1788 KB
29.txt AC 307 ms 3836 KB
30.txt AC 321 ms 2044 KB
31.txt AC 262 ms 1788 KB
32.txt AC 302 ms 1916 KB
33.txt AC 346 ms 1916 KB
34.txt AC 227 ms 1660 KB
35.txt AC 336 ms 1916 KB
36.txt AC 331 ms 2044 KB
37.txt AC 240 ms 1660 KB
38.txt AC 309 ms 1788 KB
39.txt AC 240 ms 3580 KB
40.txt AC 319 ms 1916 KB
s1.txt AC 1 ms 256 KB
s2.txt AC 1 ms 256 KB
s3.txt AC 1 ms 256 KB