Skip to content

Commit

Permalink
cutest_LIS_in_the_market.cpp & co
Browse files Browse the repository at this point in the history
  • Loading branch information
L1nkus committed Jan 16, 2022
1 parent e23c893 commit ebdffc6
Show file tree
Hide file tree
Showing 3 changed files with 344 additions and 0 deletions.
72 changes: 72 additions & 0 deletions cyclical_equivalence.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/* #pragma GCC optimize("O3,unroll-loops") */
/* #pragma GCC optimize("Ofast,unroll-loops") */
/* #pragma GCC target("avx2,popcnt") */
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#define pb push_back
#define mp make_pair
#define all(a) begin(a),end(a)
#define FOR(x,val,to) for(int x=(val);x<int((to));++x)
#define FORE(x,val,to) for(auto x=(val);x<=(to);++x)
#define FORR(x,arr) for(auto &x: arr)
#define FORS(x,plus,arr) for(auto x = begin(arr)+(plus); x != end(arr); ++x)
#define FORREV(x,plus,arr) for(auto x = (arr).rbegin()+(plus); x !=(arr).rend(); ++x)
#define REE(s_) {cout<<s_<<'\n';exit(0);}
#define GET(arr) for(auto &i: (arr)) sc(i)
#define whatis(x) cerr << #x << " is " << (x) << endl;
#define e1 first
#define e2 second
#define INF 0x7f7f7f7f
typedef std::pair<int,int> pi;
typedef std::vector<int> vi;
typedef std::vector<std::string> vs;
typedef int64_t ll;
typedef uint64_t ull;
#define umap unordered_map
#define uset unordered_set
using namespace std;
using namespace __gnu_pbds;

#ifdef ONLINE_JUDGE
#define whatis(x) ;
#endif
#ifdef _WIN32
#define getchar_unlocked() _getchar_nolock()
#define _CRT_DISABLE_PERFCRIT_LOCKS
#endif
template<class L, class R> ostream& operator<<(ostream &os, pair<L, R> P) { os<<"("<<P.first<<","<<P.second<<")"; return os; }
template<class L, class R> ostream& operator<<(ostream &os, map<L, R> P) { for(auto const &vv: P)os<<"("<<vv.first<<","<<vv.second<<")"; return os; }
template<class T> ostream& operator<<(ostream &os, set<T> V) { os<<"[";for(auto const &vv:V)os<<vv<<","; os<<"]"; return os; }
template<class T> ostream& operator<<(ostream &os, vector<T> V) { os<<"[";for(auto const &vv:V)os<<vv<<","; os<<"]"; return os; }
inline int fstoi(const string &str){auto it=str.begin();bool neg=0;int num=0;if(*it=='-')neg=1;else num=*it-'0';++it;while(it<str.end()) num=num*10+(*it++-'0');if(neg)num*=-1;return num;}
inline void getch(char &x){while(x = getchar_unlocked(), x < 33){;}}
inline void getstr(string &str){str.clear(); char cur;while(cur=getchar_unlocked(),cur<33){;}while(cur>32){str+=cur;cur=getchar_unlocked();}}
template<typename T> inline bool sc(T &num){ bool neg=0; int c; num=0; while(c=getchar_unlocked(),c<33){if(c == EOF) return false;} if(c=='-'){ neg=1; c=getchar_unlocked(); } for(;c>47;c=getchar_unlocked()) num=num*10+c-48; if(neg) num*=-1; return true;}template<typename T, typename ...Args> inline void sc(T &num, Args &...args){ bool neg=0; int c; num=0; while(c=getchar_unlocked(),c<33){;} if(c=='-'){ neg=1; c=getchar_unlocked(); } for(;c>47;c=getchar_unlocked()) num=num*10+c-48; if(neg) num*=-1; sc(args...); }
template<typename T> using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>; //s.find_by_order(), s.order_of_key() <- works like lower_bound
template<typename T> using ordered_map = tree<T, int, less<T>, rb_tree_tag, tree_order_statistics_node_update>;
#define debug(x...) cerr << "[" #x "]: ", [](auto... $) {((cerr << $ << "; "), ...); }(x), cerr << '\n'
#define N 1000001

// Thx Jakub Radoszewski and Your Algorytmy Tekstowe

bool equiv(string x, string y){
// x = uu; y = vv;
int n = x.size(); // |u| == |v|
x += x;
y += y;
int i = 0, j = 0;
while (i<n and j<n){
int k = 0;
while (k<n and x[i+k]==y[j+k]) ++k;
if (k==n) return true;
if (x[i+k]>y[j+k]) i += k+1; else j += k+1;
}
return false;
}

int main(){
ios_base::sync_with_stdio(0);cin.tie(0);
whatis(equiv("abaababa", "babaabaa"))
}

83 changes: 83 additions & 0 deletions up_to_3_triangular_number_np1choice2_sum_decomposition.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/* #pragma GCC optimize("O3,unroll-loops") */
/* #pragma GCC optimize("Ofast,unroll-loops") */
/* #pragma GCC target("avx2,popcnt") */
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#define pb push_back
#define mp make_pair
#define all(a) begin(a),end(a)
#define FOR(x,val,to) for(int x=(val);x<int((to));++x)
#define FORE(x,val,to) for(auto x=(val);x<=(to);++x)
#define FORR(x,arr) for(auto &x: arr)
#define FORS(x,plus,arr) for(auto x = begin(arr)+(plus); x != end(arr); ++x)
#define FORREV(x,plus,arr) for(auto x = (arr).rbegin()+(plus); x !=(arr).rend(); ++x)
#define REE(s_) {cout<<s_<<'\n';exit(0);}
#define GET(arr) for(auto &i: (arr)) sc(i)
#define whatis(x) cerr << #x << " is " << (x) << endl;
#define debug(x...) cerr << "[" #x "]: ", [](auto... $) {((cerr << $ << "; "), ...); }(x), cerr << '\n'
#define e1 first
#define e2 second
#define INF 0x7f7f7f7f
typedef std::pair<int,int> pi;
typedef std::vector<int> vi;
typedef std::vector<std::string> vs;
typedef int64_t ll;
typedef uint64_t ull;
#define umap unordered_map
#define uset unordered_set
using namespace std;
using namespace __gnu_pbds;

#ifdef ONLINE_JUDGE
#define whatis(x) ;
#define debug(x) ;
#endif
#ifdef _WIN32
#define getchar_unlocked() _getchar_nolock()
#define _CRT_DISABLE_PERFCRIT_LOCKS
#endif
template<class A, class B> auto& operator<<(ostream &o, pair<A, B> p) { return o << '(' << p.first << ", " << p.second << ')'; }
template<class T, enable_if_t<!is_same<T, string>::value, bool> = true> auto operator<<(ostream &o, T x) -> decltype(x.end(), o) { o << '{'; int i = 0; for(auto e : x) o << (", ")+2*!i++ << e; return o << '}'; }
inline void getch(char &x){while(x = getchar_unlocked(), x < 33){;}}
inline void getstr(string &str){str.clear(); char cur;while(cur=getchar_unlocked(),cur<33){;}while(cur>32){str+=cur;cur=getchar_unlocked();}}
template<typename T> inline bool sc(T &num){ bool neg=0; int c; num=0; while(c=getchar_unlocked(),c<33){if(c == EOF) return false;} if(c=='-'){ neg=1; c=getchar_unlocked(); } for(;c>47;c=getchar_unlocked()) num=num*10+c-48; if(neg) num*=-1; return true;}template<typename T, typename ...Args> inline void sc(T &num, Args &...args){ bool neg=0; int c; num=0; while(c=getchar_unlocked(),c<33){;} if(c=='-'){ neg=1; c=getchar_unlocked(); } for(;c>47;c=getchar_unlocked()) num=num*10+c-48; if(neg) num*=-1; sc(args...); }
template<typename T> using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>; //s.find_by_order(), s.order_of_key() <- works like lower_bound
template<typename T> using ordered_map = tree<T, int, less<T>, rb_tree_tag, tree_order_statistics_node_update>;
#define N 1000001

// O(n) (+removable logn tutaj), iterating over the first 2 triangular numbers and then calculating the third.
// https://en.wikipedia.org/wiki/Fermat_polygonal_number_theorem
// n(n+1)/2; zwracane n in that.
vector<int> decomp(int n){
vector<int> triang;
for(int i = 1, sum = 1; sum <= n; sum += ++i){
if(sum == n)
return {i};
triang.push_back(sum);
}
for(int i = 1, sum = 1; sum <= n; sum += ++i){
for(int x = 1, sum2 = 1; sum + sum2 <= n; sum2 += ++x){
int sum3 = n - sum - sum2;
if(sum3 == 0)
return {i, x};
if(binary_search(all(triang), sum3))
return {i, x, (int)(lower_bound(all(triang), sum3) - triang.begin() + 1)};
}
}
assert(0);
}

int main(){
ios_base::sync_with_stdio(0);cin.tie(0);
FOR(i,1,2321313){
auto xd = decomp(i);
int s = 0;
FORR(i,xd){
s += i*(i+1)/2;
}
debug(i, xd);
assert(s == i);
}
}

189 changes: 189 additions & 0 deletions vertex_cover_parametrized_kernelization.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
#pragma GCC optimize("O3,unroll-loops")
#pragma GCC target("avx2,popcnt,fma")
#include <bits/stdc++.h>
using namespace std;
using LL = long long;
#define FOR(i, l, r) for(int i = (l); i <= (r); ++i)
#define REP(i, n) FOR(i, 0, (n) - 1)
#define ssize(x) int(x.size())
template<class A, class B> auto& operator<<(ostream &o, pair<A, B> p) {
return o << '(' << p.first << ", " << p.second << ')';
}
template<class T> auto operator<<(ostream &o, T x) -> decltype(x.end(), o) {
o << '{'; int i = 0; for(auto e : x) o << (", ")+2*!i++ << e; return o << '}';
}
ostream& operator<<(ostream &o, string &s) {
return o << s.data();
}
#ifdef DEBUG
/* #ifdef LOCAL */
#define debug(x...) cerr << "[" #x "]: ", [](auto... $) {((cerr << $ << "; "), ...); }(x), cerr << '\n'
#else
#define debug(...) {}
#endif
// https://codeforces.com/gym/102835/problem/D

int main(){
cin.tie(0)->sync_with_stdio(0);
int n, m;
cin >> n >> m;
if(n == 2){
cout << "1\n";
return 0;
}
/* set<int> adj[n]; */
/* set<int> adj[31000]; */
/* set<int> adj[31000]; */
vector<int> adj[31000];
REP(i,m){
int f,s;
cin >> f >> s;
/* adj[f].insert(s); */
/* adj[s].insert(f); */
adj[f].push_back(s);
adj[s].push_back(f);
}
REP(i,n)
sort(adj[i].begin(), adj[i].end());
constexpr int origk = 28;
int k = 28;
bool erasd[n];
memset(erasd,0,n);
/* // na pałę liniowo this part, though could smarter. */
/* // Part 1. Wywalenie all z deg > k. */
bool cont = 1;
for(;cont;){
cont = 0;
for(int i = 0; i < n; ++i){
if(erasd[i])
continue;
if(adj[i].size() > k){
if(k <= 0){
cout << "-1\n";
return 0;
}
for(auto &x: adj[i])
/* adj[x].erase(i); */
adj[x].erase(lower_bound(adj[x].begin(), adj[x].end(), i));
erasd[i] = 1;
--k;
cont = 1;
break;
}
}
}
/* // Reguła 2. |E| > k^2 -> -1. */
vector<int> rem;
int edgecnt = 0;
for(int i = 0; i < n; ++i){
if(!erasd[i] && adj[i].size()){
rem.push_back(i);
edgecnt += adj[i].size();
}
}
// wait, podwójnie policzony miałem xd.
edgecnt >>= 1;
if(edgecnt > k * k){
cout << "-1\n";
return 0;
}
static bool vis[31000];
/* bool vis[n]; */
/* memset(vis, 0, n); */
/* auto bt = [&](vector<int> rem, int k){ */
debug(rem);
auto bt = [&](auto self, int depth){
int mxdeg = 0;
int whnode = -1;
for(auto &i: rem){
int crdeg = 0;
for(auto &x: adj[i]){ // way slower with adj as a set here obv.
// (202ms without a set, even though this still is quite dumb)
// Radeoosh has same, but without kernelization. Ja mem TLE bez
// kernelization
crdeg += binary_search(rem.begin(), rem.end(), x);
}
if(crdeg > mxdeg){
mxdeg = crdeg;
whnode = i;
}
}
if(!~whnode)
return 0;
if(depth >= k)
return 1; // 1 + depth > k, czyli i tak zle by wychodziło. Very important. That's the difference between tle and not tle. Gotta limit the depth as far as is needed.
// Or just do not wyifowańsko tego xd.
// XD, it's actually faster without this.
/* if(mxdeg <= 2){ */
/* // Łatwo rozwiązać. Chainy (m == n - 1) -> n / 2 floor; Cykle (m == n) -> n / 2 ceil. -> m / 2 ceil. */
/* int add = 0; */
/* vector<int> cleanupvec; */
/* for(auto &i: rem){ */
/* int ilem = 0; */
/* auto d1 = [&](auto self, int v) -> void{ */
/* cleanupvec.push_back(v); */
/* /1* debug(v); *1/ */
/* vis[v] = 1; */
/* for(auto &i: adj[v]){ */
/* if(!binary_search(rem.begin(), rem.end(), i)) */
/* continue; */
/* ++ilem; // can't be pod !vis[i], no bo moze byc cycle; lepiej tak, i >>= 1 potem simply. */
/* if(!vis[i]){ */
/* /1* debug(v, i); *1/ */
/* /1* ++ilem; *1/ */
/* self(self, i); */
/* } */
/* } */
/* }; */
/* if(!vis[i]){ */
/* d1(d1, i); */
/* debug(i, ilem); */
/* ilem >>= 1; */
/* add += (ilem + 1) >> 1; */
/* } */
/* } */
/* for(auto &i: cleanupvec) */
/* vis[i] ^= 1; */
/* /1* for(auto &i: rem){ *1/ */
/* /1* auto d2 = [&](auto self, int v) -> void{ *1/ */
/* /1* vis[v] = 0; *1/ */
/* /1* for(auto &i: adj[v]){ *1/ */
/* /1* if(!binary_search(rem.begin(), rem.end(), i)) *1/ */
/* /1* continue; *1/ */
/* /1* if(vis[i]){ *1/ */
/* /1* self(self, i); *1/ */
/* /1* } *1/ */
/* /1* } *1/ */
/* /1* }; *1/ */
/* /1* if(vis[i]){ *1/ */
/* /1* d2(d2, i); *1/ */
/* /1* } *1/ */
/* /1* } *1/ */
/* debug(rem, add); */
/* return add; */
/* } */
vector<int> origrem = rem;
rem.erase(lower_bound(rem.begin(), rem.end(), whnode));
int wh = 1 + self(self, depth + 1); // dodajemy whnode do vertex cover.
/* rem.insert(lower_bound(rem.begin(), rem.end(), whnode), whnode); */
// don't have to reinsert this one actually.
for(auto &i: adj[whnode]){
if(binary_search(rem.begin(), rem.end(), i)){
rem.erase(lower_bound(rem.begin(), rem.end(), i));
}
}
wh = min(wh, mxdeg + self(self, depth + mxdeg)); // dodajemy adj(whnode) do vertex cover.
rem = origrem;
return wh;
};
int ret = bt(bt, 0);
if(ret <= k){
k -= ret;
// max dopełnienie vertex coveru.
cout << n - (origk - k) << '\n';
}
else{
cout << "-1\n";
}
}

0 comments on commit ebdffc6

Please sign in to comment.