Блог пользователя atcoder_official

Автор atcoder_official, история, 7 месяцев назад, По-английски

We will hold AtCoder Beginner Contest 356.

We are looking forward to your participation!

  • Проголосовать: нравится
  • +102
  • Проголосовать: не нравится

»
7 месяцев назад, # |
  Проголосовать: нравится -32 Проголосовать: не нравится

vERY gOOd AtcodeR,making mY cOdE SpIn.

»
7 месяцев назад, # |
  Проголосовать: нравится -70 Проголосовать: не нравится

有中国人吗?

»
7 месяцев назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

is this hard?

  • »
    »
    7 месяцев назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится

    Yes.

    • »
      »
      »
      7 месяцев назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится

      i can only answer the first problem, lol. i'm stuck at the 2nd and the 3rd one. is the 2nd problem use dynamic programming?

      • »
        »
        »
        »
        7 месяцев назад, # ^ |
          Проголосовать: нравится 0 Проголосовать: не нравится

        Please discuss after contest

      • »
        »
        »
        »
        7 месяцев назад, # ^ |
          Проголосовать: нравится 0 Проголосовать: не нравится

        I can answer the first and the second problems.But I have no time to answer the third problem.

      • »
        »
        »
        »
        7 месяцев назад, # ^ |
          Проголосовать: нравится 0 Проголосовать: не нравится

        I know the first, second, third, fourth, and fifth questions. The competition has ended, and I definitely have time to answer them for you, but I'm going to sleep. You can check my submission records. My name is Littlesnake, and I wish you good luck, buddy.

      • »
        »
        »
        »
        7 месяцев назад, # ^ |
          Проголосовать: нравится 0 Проголосовать: не нравится

        second:

        # include <bits/stdc++.h>
        
        using namespace std;
        
        int n, m, X[110][110], A[110], B[110];
        
        int main () {
        
        	cin >> n >> m;
        	for (int i = 1; i <= m; i ++) cin >> A[i];
        	for (int i = 1; i <= n; i ++) {
        		for (int j = 1; j <= m; j ++) {
        			cin >> X[i][j];
        			B[j] += X[i][j];
        		}
        	}
        	for (int i = 1; i <= m; i ++) {
        		if (B[i] < A[i]) {
        			cout << "No";
        			return 0;
        		}
        	}
        	cout << "Yes";
        
        	return 0;
        }
        
        
»
7 месяцев назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

You are right. But G is only 575 pts?

»
7 месяцев назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

Hope everyone to have fun! And I hope a positive delta.I've already got negative deltas for a long time(only 4 probs)...

»
7 месяцев назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

Hope for a funny and relaxing contest on International Children's Day.

  • »
    »
    7 месяцев назад, # ^ |
      Проголосовать: нравится -12 Проголосовать: не нравится

    International Children's Day is on November 20th to commemorate the Declaration of the Rights of the Child by the United National General Assembly on November 20th, 1959.

    June 1st is celebrated as Children's Day primarily in communist and post-communist countries. The date was arbitrarily selected by the Women's International Democratic Federation in Moscow on November 4th, 1949.

    The United Nations has more authority in setting up international holidays.

»
7 месяцев назад, # |
  Проголосовать: нравится -8 Проголосовать: не нравится

Happy Children's Day!

»
7 месяцев назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

Good luck.

»
7 месяцев назад, # |
  Проголосовать: нравится -8 Проголосовать: не нравится

Happy Children's day!

»
7 месяцев назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

Interesting problems, this was a bit tougher than 355. My second ABC and it feels so much more diverse and balanced than recent CF rounds, great job.

Sadly rounding down in E ruins such a beautiful solution:

for a in aa {
    sum -= a;
    ans += sum / a;
}

Couldn't find fix for it.

»
7 месяцев назад, # |
  Проголосовать: нравится +3 Проголосовать: не нравится

Why O(max(a) * log(max(a))) gives TLE in E?

»
7 месяцев назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

Whats the mistake in my code for problem-C ? Code

  • »
    »
    7 месяцев назад, # ^ |
    Rev. 5   Проголосовать: нравится 0 Проголосовать: не нравится

    I think the problem is the logic you use to check if a key configuration is valid or not. For example, if popcount(i) < k you never increase ans. But consider for example the test case

    1 1 1

    1 1 x

    i = 0 is a valid configuration here but popcount(i) < k.

»
7 месяцев назад, # |
  Проголосовать: нравится +29 Проголосовать: не нравится

Why is today's G only worth 575 points? I think it is as hard as last round's G, which is 650 points. (and the statistics agrees with me too!)

  • »
    »
    7 месяцев назад, # ^ |
      Проголосовать: нравится -15 Проголосовать: не нравится

    AtCoder Beginner Contests always have one too few testers for an accurate difficulty perception.

»
7 месяцев назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

What's the matter with my segment tree algorithm on problem E?

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
using namespace std;
pair<long long,long long>b[200010];
long long n,a[200010],tree1[800010],tree2[800010],lazy[800010];
map<pair<long long,long long>,long long>id;
void change1(long long now,long long l,long long r,long long x,long long k)
{
	if(r<x||l>x) return;
	if(l==r)
	{
		tree1[now]=k;
		return;
	}
	long long mid=(l+r)>>1;
	if(x<=mid) change1(now<<1,l,mid,x,k);
	else change1(now<<1|1,mid+1,r,x,k);
	tree1[now]=tree1[now<<1]+tree1[now<<1|1];
}
long long find1(long long now,long long l,long long r,long long x,long long y)
{
	if(r<x||l>y) return 0;
	if(x<=l&&r<=y) return tree1[now];
	long long mid=(l+r)>>1,res=0;
	if(x<=mid) res+=find1(now<<1,l,mid,x,y);
	if(y>mid) res+=find1(now<<1|1,mid+1,r,x,y);
	return res;
}
void push_down(long long now,long long l,long long r)
{
	long long mid=(l+r)>>1;
	lazy[now<<1]=lazy[now];
	lazy[now<<1|1]=lazy[now];
	tree2[now<<1]+=lazy[now]*(mid-l+1);
	tree2[now<<1|1]+=lazy[now]*(r-mid);
	lazy[now]=0;
}
void change2(long long now,long long l,long long r,long long x,long long y,long long k)
{
	if(r<x||l>y) return;
	if(x<=l&&r<=y)
	{
		lazy[now]=k;
		tree2[now]+=k*(r-l+1);
		return;
	}
	push_down(now,l,r);
	long long mid=(l+r)>>1;
	if(x<=mid) change2(now<<1,l,mid,x,y,k);
	if(y>mid) change2(now<<1|1,mid+1,r,x,y,k);
	tree2[now]=tree2[now<<1]+tree2[now<<1|1];
}
long long find2(long long now,long long l,long long r,long long x,long long y)
{
	if(r<x||l>y) return 0;
	if(x<=l&&r<=y) return tree2[now];
	push_down(now,l,r);
	long long mid=(l+r)>>1,res=0;
	if(x<=mid) res+=find2(now<<1,l,mid,x,y);
	if(y>mid) res+=find2(now<<1|1,mid+1,r,x,y);
	return res;
}
int main()
{
	scanf("%lld",&n);
	for(long long i=1;i<=n;i++)
	{
		scanf("%lld",&a[i]);
		b[i].first=a[i];
		b[i].second=i;
	}
	stable_sort(b+1,b+n+1);
	for(long long i=1;i<=n;i++) id[b[i]]=i;
	long long ans=0;
	for(long long i=1;i<=n;i++)
	{
		long long tmp=id[make_pair(a[i],i)];
		long long tmp2=find1(1,1,n,tmp+1,n);
		ans+=tmp2/a[i];
		change1(1,1,n,tmp,1);
		change2(1,1,n,1,tmp-1,a[i]);
	}
	for(long long i=1;i<=n;i++)
	{
		long long tmp=find2(1,1,n,1,i-1);
		if(tmp==0) continue;
		ans+=tmp/b[i].first;
	}
	printf("%lld\n",ans);
}

It can't even AC any of the examples.

»
7 месяцев назад, # |
Rev. 2   Проголосовать: нравится +1 Проголосовать: не нравится

Can someone explain why my logics for C & D fail?

For C, I iterate over each possible subset and check if it does not contradict with the tests.

Spoiler

For D, I iterate over 1's in M, and count the number of 1's on i's position through k: 0->N. The counting can be done in O(1) since on i's position 0's and 1's are alternating like this: 01010101 (for bit 0) 00110011 (for bit 1) 00001111 (for bit 2) ...

Spoiler
  • »
    »
    7 месяцев назад, # ^ |
      Проголосовать: нравится +1 Проголосовать: не нравится

    For C, your code does not consider the possibility that there are no real keys (I made the same mistake). Consider this test case:

    1 1 1
    1 1 x
    

    The answer is 1 but your code gives 0.

    For D, I think there is an off by one error somewhere when you are calculating add. Consider this test case:

    4 4
    

    The answer is 1 but your code gives 0.

»
7 месяцев назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

for E : How to find the remainder of the values which are greater than a[i] for every a[i] efficiently.

  • »
    »
    7 месяцев назад, # ^ |
    Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится

    I don't think you can

    So ideas along the lines of $$$\lfloor\frac{a}{b}\rfloor = \frac{a-a\%b}{b}$$$ don't work because it's hard to calculate the sum of $$$a\%b$$$ quickly

  • »
    »
    6 месяцев назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится

    Here is an idea with the complexity of $$$O(\sum \limits_{i = 1}^n (a_i \sqrt{a_i}))$$$:

    You should remember these two theorems:

    1. For a fixed integer $$$n$$$, there is at most $$$O(\sqrt{n})$$$ different values of $$$\lfloor \frac{n}{i} \rfloor$$$.

    2. For a fixed integer $$$n$$$, assume $$$l$$$ is the minimum value of $$$i$$$ such that $$$\lfloor \frac{n}{i} \rfloor = x$$$, then the maximum value of $$$i$$$ satisfies the condition is $$$\lfloor \frac{n}{\lfloor \frac{n}{l} \rfloor} \rfloor$$$.

    Then pre-calculate the times of occurences of each value, then use these theorems to create a simple method:

    For each time, get an interval $$$[l, r]$$$ such that $$$\frac{n}{l} = \frac{n}{l + 1} = \cdots = \frac{n}{r}$$$, calculate the answer in $$$[l, r]$$$(it is easy), until $$$l > n$$$ where $$$n$$$ is the current value.

»
7 месяцев назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

Problem F can be solved by dividing into sqrt(Q) blocks of queries :D, I love sqrt decomposition.

  • »
    »
    7 месяцев назад, # ^ |
      Проголосовать: нравится +3 Проголосовать: не нравится

    Or by love with multiple sets

    Assume current set is $$$[1, 5, 10, 14, 19]$$$ and $$$K = 4$$$. Let's look at segments between each two consecutive elements: $$$[[1, 5], [5, 10], [10, 14], [14, 19]]$$$. Now lets leave only those, whose length is greater than $$$K$$$ and take only left points out of two: $$$[5, 14]$$$.

    Assume, the query is $$$1$$$. We apply lower_bound to this set and get $$$14$$$. This is the right point in connected component, that we are looking for. Now use indexed_set to find its number in original set.

    To find left point in connected component use another set (Why C++ doesn't have xxx_bound to left direction...).

    • »
      »
      »
      7 месяцев назад, # ^ |
      Rev. 2   Проголосовать: нравится +3 Проголосовать: не нравится

      I don't actually use indexed_set anymore as it won't help me a lot in offline contests (I can't use the extension library) but thanks for another way to solve the problem! I've also thought about getting the index first but I forgot about indexed sets hehe :D

      • »
        »
        »
        »
        7 месяцев назад, # ^ |
          Проголосовать: нравится +3 Проголосовать: не нравится

        Actually, I think it is a good idea to learn just this magic line, as it helps me quite often. I guess, the only another way to do it is by implementing cartesian tree by hands, which is far worse idea for offline contest.

        typedef tree<int,null_type,less<int>,rb_tree_tag, tree_order_statistics_node_update> indexed_set;
        
        • »
          »
          »
          »
          »
          7 месяцев назад, # ^ |
            Проголосовать: нравится +3 Проголосовать: не нравится

          the problem is that our offline judge (known as Themis) doesn't support extended libraries so maybe (just maybe) I can instead use a trie to store

    • »
      »
      »
      7 месяцев назад, # ^ |
      Rev. 2   Проголосовать: нравится +3 Проголосовать: не нравится

      I did something similar, but with 4 sets (set of current points, ordered_set of current points, set of points whose closest point on the left is at a distance > K, set of points whose closest point on the right is at a distance > K). Here's the submission. Tbh I was surprised by the low solve count.

      Sadly, I entered contest 1 hour after the start and missed out on +100 delta :(.

  • »
    »
    7 месяцев назад, # ^ |
      Проголосовать: нравится +3 Проголосовать: не нравится

    Mo's algo and DSU, the one in the EDU section?

»
7 месяцев назад, # |
  Проголосовать: нравится +3 Проголосовать: не нравится

why range based segment tree won't work for Problem F ?


#include <bits/stdc++.h> #define int long long using namespace std; struct Bird { int Value; // Minimum value of a segment Bird *LeftChild, *RightChild; // Pointers to left child and right child Bird() // Constructor { Value = 0; LeftChild = NULL; RightChild = NULL; } void BirdLay() // Construct Childs { if (LeftChild == NULL) LeftChild = new Bird(); if (RightChild == NULL) RightChild = new Bird(); } }; Bird* Root = new Bird(); // The first Node that manage [1, N] Bird* Root1 = new Bird(); // The first Node that manage [1, N] void BirdPerch(Bird *Current, int curL, int curR, int Pos, int newValue) { if (curL > Pos || curR < Pos) { // Pos is not in range [curL, curR] return; } if (curL == curR) { // Current is the Node that manage only Posth element Current -> Value = newValue; return; } int mid = (curL + curR) / 2; Current -> BirdLay(); BirdPerch(Current -> LeftChild, curL, mid, Pos, newValue); BirdPerch(Current -> RightChild, mid + 1, curR, Pos, newValue); Current -> Value = (Current -> LeftChild -> Value + Current -> RightChild -> Value); } int BirdFly(Bird *Current, int curL, int curR, int L, int R) { if (curL > R || curR < L) { // [curL, curR] doesn't intersect with [L, R] return 0; } if (L <= curL && curR <= R) { // [curL, curR] is inside [L, R] return Current -> Value; } int mid = (curL + curR) / 2; Current -> BirdLay(); return (BirdFly(Current -> LeftChild, curL, mid, L, R) + BirdFly(Current -> RightChild, mid + 1, curR, L, R)); } int32_t main() { ios_base::sync_with_stdio(false); cin.tie(0); int N, Q; cin >> N; int q; int k; cin>>k; Q = N; char Type; int Pos, newValue, L, R; int mt = 1e16; for(int i = 0; i < N; i++){ int t; cin>>t; if(t == 1){ int x; cin>>x; int s = BirdFly(Root1, 1, mt, x, x); if(s == 1){ // if already there delete it //cout<<x<<endl; BirdPerch(Root1, 1, mt, x, -1); } else { BirdPerch(Root1, 1, mt, x, 1); } } else { int x; cin>>x; int s = BirdFly(Root1, 1, mt, max(1ll*0, x - k), x + k); cout<<s<<endl; } } //cout<<res<<endl; }
»
7 месяцев назад, # |
Rev. 3   Проголосовать: нравится +9 Проголосовать: не нравится

Problem setter, I don't know who you are, but I love you, you are amazing! =)

I laughed so hard when I solved problem C and read the problem statement of D =))))

Problem A is very ez, but was so satisfying to solve with clean c++ std. Pure joy =))

Problem A
»
7 месяцев назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

How to solve problem E. The editorial is too complex for me.

  • »
    »
    7 месяцев назад, # ^ |
      Проголосовать: нравится +7 Проголосовать: не нравится

    At first assume, that there are no repeating numbers.

    First let's sort the array. Assume, we have following: $$$[1, 2, 4, 5]$$$. We are calculating following: $$$(2 / 1 + 4 / 1 + 5 / 1) + (4 / 2 + 5 / 2) + (5 / 4)$$$. Let's calculate it parenthesis by parenthesis.

    Assume, current number is $$$x$$$. By dividing which numbers by $$$x$$$ we get $$$1$$$? Numbers $$$x, x+1, \dots, 2x - 1$$$. By dividing which numbers by $$$x$$$ we get $$$y$$$? Numbers $$$xy, xy + 1, \dots, (x+1)y - 1$$$. Let's instead of original array use array of occurences: $$$[1, 1, 0, 1, 1, 0, 0, 0, \dots]$$$, which means, there is one occurence of $$$1$$$, one occurence of $$$2$$$, zero occurences of $$$3$$$, etc. Let's build prefix sums $$$ps$$$ on this array. Now the required number is $$$ps[(x + 1)y] - ps[xy]$$$.

    We need to iterate over all possible $$$y$$$. But aren't there too many of them? We don't need to have $$$xy > 10^6 = C$$$, because there will be only zeros in array of occurences. So $$$y \le \frac{C}{x}$$$. Number of iterations will be $$$\frac{C}{1} + \frac{C}{2} + \frac{C}{3} + \dots + \frac{C}{C} = C(\frac{1}{1} + \frac{1}{2} + \frac{1}{3} + \dots + \frac{1}{C})$$$. The expression in parenthesis is well-known. It is called harmonic series and is approximately equal to $$$\ln(C)$$$. So if we simply iterate over all $$$x$$$ and $$$y$$$ up to $$$\frac{C}{x}$$$ it will be $$$C \cdot \ln(C)$$$ time.

    About repeating number. In straightforward implementation all pairs of repeated numbers will be calculated, but we need to calculate them left to right direction. To do it, we can simply subtract all extra pairs by $$$res -= \frac{cnt(cnt + 1)}{2}$$$.

    • »
      »
      »
      7 месяцев назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится

      I was thinking on sorting numbers in descending order and then for each number calculate how many numbers are in range >= x & < 2x, >= 2x & <3 x, .....

      I was thinking to do this by binary search. Can it be done better?

      • »
        »
        »
        »
        7 месяцев назад, # ^ |
          Проголосовать: нравится +3 Проголосовать: не нравится

        We can leave the original sorted array. For each number $$$x$$$ in the array iterate on all $$$y$$$ and find corresponding segment $$$[xy, (x+y)y - 1]$$$ by binary search.

        But we also need to not iterate on same value $$$x$$$ several times, if it has several occurences. We need to do it once and then multiply by the number of occurences and also add the binomial coefficient of number of ordered pairs of these repeated elements.

        It is $$$C \cdot \ln(C) \cdot \log(n)$$$ and looks harder to implement.

      • »
        »
        »
        »
        7 месяцев назад, # ^ |
          Проголосовать: нравится 0 Проголосовать: не нравится

        Yes, create an array that holds the count of each number, and you can easily calculate the count of numbers between a and b using prefix sums.

    • »
      »
      »
      7 месяцев назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится

      Could you help me understand how sorting does not change the answer say our array is [2 10 10 10 1] then 2/1 pair will never come but in sorted array it does appear

»
7 месяцев назад, # |
Rev. 4   Проголосовать: нравится 0 Проголосовать: не нравится

MySolution Can anyone please tell me what is wrong in my solution for C — Keys? ;)

  • »
    »
    7 месяцев назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится

    A lot of people (including me) are making the same mistake for C, consider this test case:

    1 1 1
    1 1 x
    

    The answer is 1 but your code gives 0.

»
7 месяцев назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится
»
7 месяцев назад, # |
Rev. 2   Проголосовать: нравится +3 Проголосовать: не нравится

In F, I used DCP offline on unordered_maps

Code
Explanation
»
7 месяцев назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

Atcoder should have a NO AI TEST

  • »
    »
    7 месяцев назад, # ^ |
    Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится

    If you take a look at the fastest submissions of A,C,D,you'll find that they are apparently written by AI.By the way,this and this didn't delete the comment "Generated by OpenAI gpt-4o".(Laugh)

»
7 месяцев назад, # |
Rev. 2   Проголосовать: нравится +8 Проголосовать: не нравится

F using binary search and segment tree. For a x, we need to know the leftmost element having absolute different with element to it's left > k. In the same way we will find the rightmost element having absolute different with element to it's right > k. Now we have 2 indexes a and b. The answer will be no of element in the range [a, b] which are still part of S. Sorry for my bad English.

»
7 месяцев назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

for e may someone tell me what is matter of my code?

#include <iostream>

using namespace std;

const int N = 1e6 + 10;

typedef long long LL;
int a[N], cnt[N];
LL s[N];

int main() {
    int n;
    cin >> n;
    for(int i = 1; i <= n; i ++ ) {
        cin >> a[i];
        cnt[a[i]] ++;
    }
    // x --- 2x - 1 --> 1; 2x --- 3x - 1 --> 2
    for(int i = 1; i <= 1000000; i ++ ) s[i] = s[i - 1] + cnt[i];
    LL ans = 0;
    for(int i = 1; i <= 1000000; i ++ ) {
        if(!cnt[i]) continue;
        for(int j = i; j <= 1000000; j += i) {
            int r = min(j + i - 1, 1000000);
            ans += (long long)cnt[i] * (s[r] - s[j - 1]) * (r / i);
        }
        if(cnt[i] > 1) {
            ans -= cnt[i];
            ans += ((long long)cnt[i] * cnt[i] - 1) / 2;
        }
    }
    cout << ans - n;
    return 0;
}
»
7 месяцев назад, # |
Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится

In problem C, the following solution of mine got AC. I thought it would be a TLE. What I did is calculate for every combination using bitmask. In worse case it is O((2^N)*M*N)=O((2^15)*100*15)=49,152,000. Can someone please explain why is it not TLE?

my solution

»
7 месяцев назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

a complete beginner here, where would one rate the difficulty of this challenge? This was my first CC at I could only crack the first two.

»
7 месяцев назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

https://atcoder.jp/contests/abc356/submissions/54163403

Any idea why a simple functional implementation would give wrong answer rather than tle?

»
6 месяцев назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

Where can one find the complete set of test cases for problem E for this contest?