One Point Solution

  • Subscribe to our RSS feed.
  • Twitter
  • StumbleUpon
  • Reddit
  • Facebook
  • Digg

Friday, 7 June 2013

Codeforces Round 187

Posted on 10:54 by Unknown

I don't participate in codeforces rounds as much as I'd like. But it is hard enough to free my schedule to participate in TopCoder rounds (and I need to participate because it is my job to write editorials), then writing the editorials consumes quite a lot part of each week. Today I finally found a period of time in which I am both willing to try a codeforces round and I feel like I have time. So this happened.

Problem C - Sereja and Subsequences

Link to problem

I remember getting bored with the first two problems of division 1 codeforces, so this time I decided to start with the C.

In this problem, you like to find the sum of the products of each unique non-decreasing subsequence of a sequence. For example, if the unique non-decreasing subsequences were {1},{2} and {1,2}, the result is (1) + (2) + (1*2) .

An easy version

Let us forget that the maximum number of integers in the sequence is 10^5 and solve a slower version. This is a simple dynamic programming solution.

Let f(i) the sum of all the products of subsequences that start with seq[i]. It is easy to calculate it for i=N-1 (Base case). For other cases:

  • f(i) is at least seq[i], because there is a subsequence that contains only seq[i].
  • Else we need to find indexes j for subsequences starting with seq[j], so that we append seq[i] in front of the subsequences. We multiply seq[i] to the count of f(j) to find the sum of those products. however, in order not to repeat subsequences, we need j to be the smallest index that has value equal to seq[j].

The final result is to add up all res[i], whenever i is the smallest index to have value equal to seq[i].

const long MOD = 1000000007;
int N;
long seq[100000];
long res[1000001];

int solve()
{
memset(res, 0, sizeof(res));
for (int i=N-1; i >= 0; i--) {
long nw = seq[i];

for (int j=seq[i]; j <= 1000000; j++) {
if (seq[j] >= seq[i]) {
bool seen = false;
for (int k=i+1; k<j; k++) {
seen |= (seq[j] == seq[k]);
}
if (! seen) {
res[i] = (res[i] + seq[i] * res[j] ) % MOD;
}
}
}
}
long total = 0;
for (int i=0; i<N; i++) {
bool seen = false;
for (int j=0; j<i; j++) {
seen |= (seq[j] == seq[i]);
}
if (! seen) {
total = (total + res[i]) % MOD;
}
}
return total;
}

A less easy version

Instead of making sure the index j is the smallest index with value equal to seq[j], we can save up the work by replacing the function of the res[i] array, this time it returns the currently-known sum of products of subsequences that start with i (not seq[i]).

Then the dp looks like this:

const long MOD = 1000000007;
int N;
long seq[100000];
long res[1000001];

int solve()
{
memset(res, 0, sizeof(res));
for (int i=N-1; i >= 0; i--) {
long nw = seq[i];

for (int j=seq[i]; j <= 1000000; j++) {
nw = (nw + seq[i]* res[j] ) % MOD;
}
res[i] = nw;
}
long total = 0;
for (int i=1; i<1000000; i++) {
total = (total + res[i]) % MOD;
}
return total;
}

Final one

In each step i, we just need to find the sum of all res[j] such that j >= seq[i]. Then replace res[i] with a new value. At the end, we need the sum of all res[j] such that j is >= 0. We can implement this solution using a tree. A special data structure that can quickly return the sum of all inserted values greater than or equal to an index. It should also be possible to quickly insert and remove. We can just use a binary indexed tree for this.

const long MOD = 1000000007;
int N;
long seq[100000];
long oldvalue[1<<20];

// Stuff for the tree:
// An index i is parent of 2*i+1, 2*i+2, and is related to an interval [a,b)
long tree[1<<21];

const int MIN = 0;
const int MAX = 1<<20;
void insert(int x, long value, int node=0, int a=MIN, int b=MAX)
{
tree[node] = (tree[node] + value) % MOD;
if (a < b-1) {
int left = 2*node + 1;
int right = 2*node + 2;
int m = (a + b) / 2;
if (x < m) {
insert(x,value, left, a, m);
} else {
insert(x,value, right, m, b);
}
}
}

long sum(int x, int node=0, int a=MIN, int b=MAX)
{
if (a >= x) {
return tree[node];
}
if (b <= x) {
return 0;
}
int m = (a + b) / 2;
int left = 2*node + 1;
int right = 2*node + 2;
long p = sum(x, left,a,m);
long q = sum(x, right,m,b);
return (p + q) % MOD;
}

int solve()
{
memset(tree, 0, sizeof(tree) );
memset(oldvalue, 0, sizeof(oldvalue));
for (int i=N-1; i >= 0; i--) {
// New value:
long nw = (seq[i] * (1 + sum(seq[i])) ) % MOD;
// This should remove the old value:
insert(seq[i], MOD - oldvalue[seq[i]] );
oldvalue[seq[i]] = nw;
// Insert the new value:
insert(seq[i], nw);
}
return sum(0);
}

Other problems

I opened B, decided to go to lunch while I think about it.

Apparently lunch took much longer than planned. When I came back to my computer I started to write and continued to think of a solution. I think it is correct, but when I was in the middle of debugging it, I noticed that there were only 15 minutes left for the match. Eventually finished coding it with two minutes left. I hope it is all right.

Update: Just as I finished writing this post, I found out my B was wrong. Well, I didn't have high expectations for that rushed solution.

Update 2: "Hot news" http://codeforces.com/bestRatingChanges/249522. All hail vexorian the orange.

Email ThisBlogThis!Share to XShare to Facebook
Posted in codeforces, explanation, recap | No comments
Newer Post Older Post Home

0 comments:

Post a Comment

Subscribe to: Post Comments (Atom)

Popular Posts

  • TopCoder SRM 557 - finally
    SRM 557 Explanation for division 1 Easy and match recap. Explanations for div2 easy and div2 medium. It feels like it has been ages since t...
  • SRM 589 Editorial
    I have finished writing the editorial for TopCoder SRM 589: http://apps.topcoder.com/wiki/display/tc/SRM+589 . As you most likely noticed. L...
  • SRM 590 recap and editorial
    Another week another Topcoder match. Not a great day. I had a bad flu and still do. Div1 500: The one with Xor Given a list of cards with nu...
  • SRM 546: relief
    I figured I should post something about this SRM. I've been very busy these weeks because the semester is ending and I tried to win a t-...
  • SRM 526: The killing wait for results
    While I wait for results, here is my perspective on this algorithm contest. It began with issues, it had to be postponed 15 minutes. TC has ...
  • SRM 554 div1 hard: TheBrickTowerHardDivOne
    Link to problem statement We got infinitely many bricks of dimensions 1x1x1 and C different colors. Count the number of towers of size 2x2...
  • SRM 533: Div1 500 MagicBoard explanation
    Finally solved it. It is a nice problem that is worth explaining in a post. You have a grid/board of at most 50x50 cells. Some cells contain...
  • Member SRM 505: Part 1
    So, let me explain a couple of problems from a Topcoder Member SRM that I wrote and never got an editorial. BTW, it was the last member SRM....
  • ListedLinks 2012-02-10
    Saturday Morning Breakfast Cereal comics: Grace Hopper's ghost That Oracle engineer blog post Oracle would really not like anyone to se...
  • Codeforces "Good bye 2013" round
    So it was a special round for coders of both divisions, problems ranged from the super easy problem A to the super difficult problems E,F,G....

Categories

  • acm
  • algorithm
  • answers
  • arenaplugin
  • badday
  • behindthescenes
  • bugs
  • c++
  • censorship
  • codechef
  • codeforces
  • contests
  • crocchamp
  • editorial
  • editorial.srm
  • embarrassing
  • explanation
  • gcj2013
  • gmp
  • goodday
  • google
  • googlecodejam
  • greed
  • groklaw
  • health
  • html
  • httpseverywhere
  • implementation
  • ipsc
  • ispc
  • java
  • kawigiedit
  • kindagoodday
  • lamebook
  • languages
  • lego
  • listedlinks
  • marathon
  • nasa
  • offtopic
  • ouch
  • postmortem
  • postportem
  • practical
  • probably_not_a_good_tip
  • problemsetting
  • programming
  • python
  • quora
  • rant
  • recap
  • slightlygoodday
  • snippet
  • srm
  • stl
  • strategy
  • swerc
  • tco
  • tco12
  • tco13
  • tco2012
  • tco2013
  • ternarysearch
  • topcoder
  • tricks
  • ubuntu
  • uva
  • vjass
  • vkcup
  • wc3
  • zinc

Blog Archive

  • ►  2014 (1)
    • ►  January (1)
  • ▼  2013 (141)
    • ►  December (14)
    • ►  November (8)
    • ►  October (13)
    • ►  September (11)
    • ►  August (14)
    • ►  July (15)
    • ▼  June (13)
      • TurnOnLamps editorial
      • SRM 583 Editorial preview: RandomPaintingOnABoard
      • How to fail in TopCoder Marathon round 3
      • SRM 583: Last minute (and explanations)
      • Change of plans
      • Block3Checkers editorial preview
      • TCO 2013 round 2A: I wrote the 550 points one
      • IPSC 2013
      • Codeforces Round 187
      • SRM 581 Editorial supposedly ready
      • SRM 581 - YetAnotherBoardGame editorial
      • SRM 581: Did I solve the 500?
      • Out of google codejam 2013
    • ►  May (13)
    • ►  April (12)
    • ►  March (11)
    • ►  February (11)
    • ►  January (6)
  • ►  2012 (94)
    • ►  December (5)
    • ►  October (6)
    • ►  September (8)
    • ►  August (6)
    • ►  July (3)
    • ►  June (5)
    • ►  May (8)
    • ►  April (10)
    • ►  March (20)
    • ►  February (16)
    • ►  January (7)
  • ►  2011 (51)
    • ►  December (7)
    • ►  November (12)
    • ►  October (5)
    • ►  September (1)
    • ►  August (3)
    • ►  July (4)
    • ►  June (3)
    • ►  May (7)
    • ►  April (3)
    • ►  March (2)
    • ►  February (1)
    • ►  January (3)
  • ►  2010 (9)
    • ►  December (4)
    • ►  October (1)
    • ►  June (1)
    • ►  May (1)
    • ►  January (2)
  • ►  2009 (1)
    • ►  December (1)
Powered by Blogger.

About Me

Unknown
View my complete profile