Submission #89969

# Submission time Handle Problem Language Result Execution time Memory
89969 2018-12-19T10:58:09 Z nikolapesic2802 ČVENK (COI15_cvenk) C++14
100 / 100
1719 ms 175052 KB
/*
    -The tricky part is figuring out how to construct the tree that we need to answer the question effectively.
    -For every 2^k*2^k square starting on point 0,0 the point that we are looking for can be in several "regions":"inside region", in the 2^(k-1)*2^(k-1) square,
                                                                                                                  "left region" (square of size 2^(k-1)*2^(k-1) starting on 2^(k-1),0
                                                                                                                  "up region"(square of size 2^(k-1)*2^(k-1) starting on 0,2^(k-1)
                                                                                                                  "outside region", not in the square at all(its in some bigger square)
    -Notice that if 2 points are not in the same "region", we need to go the edge of the current square to travel between them.
    -This gives us the solution to construct a tree and calculate the answer that way.
    -The construction is done recursively starting from the smallest square and calling recursively for the regions in order  "inside"->"left"->"up"->"outside" (the order of left and up doesn't matter)
    -I used a map to memorize which tree nodes to connect, it adds some time complexity but it was easier to type for me.
    -Then we need to calculate the answer by calculating the cost of moving all the tourists for every node in the tree and print the minimum (in some complexity better than O(n^2) of course).
*/
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/rope>

#define ll long long
#define pb push_back
#define sz(x) (int)(x).size()
#define mp make_pair
#define f first
#define s second
#define all(x) x.begin(), x.end()

using namespace std;
using namespace __gnu_pbds;
using namespace __gnu_cxx;

template<class T> using ordered_set = tree<T, null_type, less<T>, rb_tree_tag,tree_order_statistics_node_update>; ///find_by_order(),order_of_key()
template<class T1, class T2> ostream& operator<<(ostream& os, const pair<T1,T2>& a) { os << '{' << a.f << ", " << a.s << '}'; return os; }
template<class T> ostream& operator<<(ostream& os, const vector<T>& a) {
	os << '{';
	for(int i=0;i<sz(a);i++)
	{
		if(i>0&&i<sz(a)-1)
			os << ", ";
		os << a[i];
	}
	os << '}';
    return os;
}
void show()
{
    int n=128;
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<n;j++)
        {
            if(i&j)
                printf("%c",178);
            else
                printf("%c",176);
        }
        printf("\n");
    }
}
map<int,pair<int,int> > mapax,mapay;  ///{kordinata,poz_u_grafu}
int nxt=1;
vector<pair<int,int> > dummy;
int dummy1;
vector<vector<pair<int,int> > > graf(2);
vector<int> cnt(2);
void construct(vector<pair<int,int> > points,ll velicina,ll x,ll y)
{
    vector<pair<int,int> > posle,levo,desno,gore;
    for(auto p:points)
    {
        if(p.first>=x+velicina||p.second>=y+velicina){
            posle.pb(p);
            continue;
        }
        if(p.first<x+velicina/2&&p.second<y+velicina/2)
        {
            gore.pb(p);
            continue;
        }
        if(p.first>=x+velicina/2)
        {
            levo.pb(p);
        }
        else
        {
            desno.pb(p);
        }
    }
    if(gore.size())
    {
        construct(gore,velicina/2,x,y);
    }
    if(levo.size())
    {
        graf[mapay[y].second].pb({nxt,x+velicina/2-mapay[y].first});
        mapay[y]=make_pair(x+velicina/2,nxt);
        mapax[x+velicina/2]=make_pair(y,nxt);
        vector<pair<int,int> > ne;
        for(auto p:levo)
        {
            if(p.first==x+velicina/2&&p.second==y)
                cnt[nxt]++;
            else
                ne.pb(p);
        }
        nxt++;
        if(nxt>=graf.size())
            graf.pb(dummy),cnt.pb(dummy1);
        if(ne.size())
            construct(ne,velicina/2,x+velicina/2,y);
    }
    if(desno.size())
    {
        graf[mapax[x].second].pb({nxt,y+velicina/2-mapax[x].first});
        mapax[x]=make_pair(y+velicina/2,nxt);
        mapay[y+velicina/2]=make_pair(x,nxt);
        vector<pair<int,int> > ne;
        for(auto p:desno)
        {
            if(p.first==x&&p.second==y+velicina/2)
                cnt[nxt]++;
            else
                ne.pb(p);
        }
        nxt++;
        if(nxt>=graf.size())
            graf.pb(dummy),cnt.pb(dummy1);
        if(ne.size())
            construct(ne,velicina/2,x,y+velicina/2);
    }
    if(posle.size())
    {
        construct(posle,(ll)velicina*2,x,y);
    }
}
void printgraf(int tr)
{
    printf("Cnt od %i: %i\n",tr,cnt[tr]);
    for(auto p:graf[tr])
    {
        printf("Idem od %i do %i, tezina: %i\n",tr,p.first,p.second);
        printgraf(p.first);
    }
}
vector<int> siz;
vector<ll> val;
void postavi(int tr)
{
    siz[tr]+=cnt[tr];
    for(auto p:graf[tr])
    {
        postavi(p.first);
        siz[tr]+=siz[p.first];
        val[tr]+=val[p.first]+(ll)siz[p.first]*p.second;
    }
}
ll minn;
void get_min(int tr,ll value)
{
    minn=min(minn,value);
    for(auto p:graf[tr])
    {
        ll ne=value-(ll)siz[p.first]*p.second;
        ne+=(ll)(siz[0]-siz[p.first])*p.second;
        get_min(p.first,ne);
    }
}
int main()
{
    //show();
    int n;
    scanf("%i",&n);
    vector<pair<int,int> > points;
    for(int i=0;i<n;i++){
        int x,y;
        scanf("%i %i",&x,&y);
        if(x==0&&y==0)
            cnt[0]++;
        else
            points.pb({x,y});
    }
    mapax[0]=make_pair(0,0);
    mapay[0]=make_pair(0,0);
    construct(points,2,0,0);
    //printgraf(0);
    int N=graf.size();
    siz.resize(N);
    val.resize(N);
    postavi(0);
    minn=val[0];
    get_min(0,minn);
    printf("%lld\n",minn);
    return 0;
}

Compilation message

cvenk.cpp: In function 'void construct(std::vector<std::pair<int, int> >, long long int, long long int, long long int)':
cvenk.cpp:105:15: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
         if(nxt>=graf.size())
            ~~~^~~~~~~~~~~~~
cvenk.cpp:124:15: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
         if(nxt>=graf.size())
            ~~~^~~~~~~~~~~~~
cvenk.cpp: In function 'int main()':
cvenk.cpp:170:10: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
     scanf("%i",&n);
     ~~~~~^~~~~~~~~
cvenk.cpp:174:14: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
         scanf("%i %i",&x,&y);
         ~~~~~^~~~~~~~~~~~~~~
# Verdict Execution time Memory Grader output
1 Correct 2 ms 376 KB Output is correct
2 Correct 2 ms 376 KB Output is correct
3 Correct 2 ms 448 KB Output is correct
4 Correct 2 ms 524 KB Output is correct
# Verdict Execution time Memory Grader output
1 Correct 3 ms 856 KB Output is correct
2 Correct 3 ms 876 KB Output is correct
3 Correct 3 ms 876 KB Output is correct
4 Correct 3 ms 876 KB Output is correct
# Verdict Execution time Memory Grader output
1 Correct 62 ms 14968 KB Output is correct
2 Correct 61 ms 15264 KB Output is correct
3 Correct 43 ms 15264 KB Output is correct
4 Correct 38 ms 15264 KB Output is correct
5 Correct 47 ms 15264 KB Output is correct
# Verdict Execution time Memory Grader output
1 Correct 1719 ms 175040 KB Output is correct
2 Correct 1631 ms 175052 KB Output is correct
3 Correct 765 ms 175052 KB Output is correct
4 Correct 816 ms 175052 KB Output is correct
5 Correct 892 ms 175052 KB Output is correct