Submission #1254096

#TimeUsernameProblemLanguageResultExecution timeMemory
1254096Zbyszek99Flooding Wall (BOI24_wall)C++20
70 / 100
5096 ms238732 KiB
#include <bits/stdc++.h> #include <ext/pb_ds/assoc_container.hpp> #include <ext/pb_ds/tree_policy.hpp> #pragma GCC optimize("O3,unroll-loops") #pragma GCC target("avx2,bmi,bmi2,lzcnt,popcnt") #define ll long long #define ld long double #define ull unsigned long long #define ff first #define ss second #define pii pair<int,int> #define pll pair<long long, long long> #define vi vector<int> #define vl vector<long long> #define pb push_back #define rep(i, b) for(int i = 0; i < (b); ++i) #define rep2(i,a,b) for(int i = a; i <= (b); ++i) #define rep3(i,a,b,c) for(int i = a; i <= (b); i+=c) #define count_bits(x) __builtin_popcountll((x)) #define all(x) (x).begin(),(x).end() #define siz(x) (int)(x).size() #define forall(it,x) for(auto& it:(x)) using namespace __gnu_pbds; using namespace std; typedef tree<int, null_type, less<int>, rb_tree_tag,tree_order_statistics_node_update> ordered_set; //mt19937 mt;void random_start(){mt.seed(chrono::time_point_cast<chrono::milliseconds>(chrono::high_resolution_clock::now()).time_since_epoch().count());} //ll los(ll a, ll b) {return a + (mt() % (b-a+1));} const int INF = 1e9+50; const ll INF_L = 1e18+40; const ll MOD = 1e9+7; ll P[2000001]; ll odwP[2000001]; ll odw(ll x) { ll ans = 1; rep(bit,30) { if((MOD-2) & (1 << bit)) { ans *= x; ans %= MOD; } x *= x; x %= MOD; } return ans; } struct tag { ll i=0,x=0,c=0,d=0; tag operator+(const tag& other) { tag res; res.i = (i+((other.i*P[d])%MOD)*odwP[c])%MOD; res.x = (x+((other.x*P[d])%MOD)*odwP[c])%MOD; res.c = c+other.c; res.d = d+other.d; return res; } }; tag def; struct node { ll val_sum=0,cnt_sum=0,mul=0; void add_tag(const tag& other) { val_sum = (((val_sum+mul*other.i + cnt_sum*other.x)%MOD)*P[other.c])%MOD; mul = (mul*P[other.d])%MOD; cnt_sum = (cnt_sum*P[other.d])%MOD; } node operator+(const node& other) { node res; res.val_sum = (val_sum+other.val_sum)%MOD; res.cnt_sum = (cnt_sum+other.cnt_sum)%MOD; res.mul = (mul+other.mul)%MOD; return res; } }; int tree_siz = 1024*2048-1; tag tags[1024*2048]; node nodes[1024*2048]; void upd(int v) { tags[v*2] = (tags[v*2]+tags[v]); tags[v*2+1] = (tags[v*2+1]+tags[v]); nodes[v*2].add_tag(tags[v]); nodes[v*2+1].add_tag(tags[v]); tags[v] = def; } void add_tag(int akt, int p1, int p2, int s1, int s2, const tag& t) { if(p2 < s1 || p1 > s2) return; if(p1 >= s1 && p2 <= s2) { tags[akt] = (tags[akt]+t); nodes[akt].add_tag(t); return; } upd(akt); add_tag(akt*2,p1,(p1+p2)/2,s1,s2,t); add_tag(akt*2+1,(p1+p2)/2+1,p2,s1,s2,t); nodes[akt] = nodes[akt*2]+nodes[akt*2+1]; } pll get_seg(int akt, int p1, int p2, int s1, int s2) { if(p2 < s1 || p1 > s2) return {0,0}; if(p1 >= s1 && p2 <= s2) { return {nodes[akt].val_sum,nodes[akt].cnt_sum}; } upd(akt); pll w1 = get_seg(akt*2,p1,(p1+p2)/2,s1,s2); pll w2 = get_seg(akt*2+1,(p1+p2)/2+1,p2,s1,s2); return {(w1.ff+w2.ff)%MOD,(w1.ss+w2.ss)%MOD}; } node set_node; void set_val(int akt, int poz, int p1, int p2) { if(p1 == p2) { tags[akt] = def; nodes[akt] = set_node; return; } upd(akt); if(poz <= (p1+p2)/2) set_val(akt*2,poz,p1,(p1+p2)/2); else set_val(akt*2+1,poz,(p1+p2)/2+1,p2); nodes[akt] = nodes[akt*2]+nodes[akt*2+1]; } pll H2[500001]; ll rel_val[2000001]; pll left_dp[2][500001]; pll right_dp[2][500001]; int n; int max_siz = 0; void solve(pll* H, pll* ans0, pll* ans1, bool is = 0) { for(int i = tree_siz/2+1; i <= tree_siz; i++) { tags[i] = def; nodes[i].cnt_sum = 0; nodes[i].val_sum = 0; nodes[i].mul = 0; } for(int i = tree_siz/2; i >= 1; i--) { tags[i] = def; nodes[i] = nodes[i*2]+nodes[i*2+1]; } set_node = {0,1,rel_val[0]}; set_val(1,0,0,tree_siz/2); ll zero_pref = -1; pll dp0; pll dp1; pll H1_val; pll H2_val; rep(i,n) { dp0 = get_seg(1,0,tree_siz/2,0,H[i].ff-1); dp1 = get_seg(1,0,tree_siz/2,0,H[i].ss-1); H1_val = get_seg(1,0,tree_siz/2,H[i].ff,H[i].ff); H2_val = get_seg(1,0,tree_siz/2,H[i].ss,H[i].ss); ans0[i] = dp0; if(is) { ans0[i].ff += H1_val.ff; ans0[i].ss += H1_val.ss; ans0[i].ff %= MOD; ans0[i].ss %= MOD; } ans1[i] = dp1; if(is) { ans1[i].ff += H2_val.ff; ans1[i].ss += H2_val.ss; ans1[i].ff %= MOD; ans1[i].ss %= MOD; } dp0.ff += H1_val.ff; dp0.ss += H1_val.ss; dp0.ff %= MOD; dp0.ss %= MOD; rep2(j,zero_pref+1,H[i].ff-1) { set_node = {0,0,0}; set_val(1,j,0,tree_siz/2); } zero_pref = max(zero_pref,H[i].ff-1); set_node = {dp0.ff,dp0.ss,(rel_val[H[i].ff]*dp0.ss)%MOD}; set_val(1,H[i].ff,0,tree_siz/2); if(H[i].ff+1 <= H[i].ss-1) { tag t1 = {1,(-rel_val[H[i].ff]+MOD)%MOD,0,0}; add_tag(1,0,tree_siz/2,H[i].ff+1,H[i].ss-1,t1); } tag t2 = {1,(((-rel_val[H[i].ff]-rel_val[H[i].ss]+2*MOD)%MOD)*odwP[1])%MOD,1,1}; add_tag(1,0,tree_siz/2,H[i].ss,max_siz,t2); H2_val = get_seg(1,0,tree_siz/2,H[i].ss,H[i].ss); H2_val.ff += dp1.ff; H2_val.ss += dp1.ss; H2_val.ff %= MOD; H2_val.ss %= MOD; set_node = {H2_val.ff,H2_val.ss,(rel_val[H[i].ss]*H2_val.ss)%MOD}; set_val(1,H[i].ss,0,tree_siz/2); } } int main() { ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0); //random_start(); P[0] = 1; odwP[0] = 1; rep2(i,1,2000000) { P[i] = (P[i-1]*2)%MOD; odwP[i] = odw(P[i]); } cin >> n; vl a(n); vl b(n); rep(i,n) cin >> a[i]; rep(i,n) cin >> b[i]; rep(i,n) if(a[i] > b[i]) swap(a[i],b[i]); map<ll,int> m; rep(i,n) m[a[i]] = 1; rep(i,n) m[b[i]] = 1; int cur = 1; forall(it,m) { rel_val[cur] = it.ff; m[it.ff] = cur++; } max_siz = cur; tree_siz = (1 << (__lg(max_siz)+2))-1; rep(i,n) { H2[i] = {m[a[i]],m[b[i]]}; } solve(H2,left_dp[0],left_dp[1],1); reverse(H2,H2+n); solve(H2,right_dp[0],right_dp[1]); reverse(H2,H2+n); reverse(right_dp[0],right_dp[0]+n); reverse(right_dp[1],right_dp[1]+n); ll ans = 0; rep(i,n) { rep(d,2) { ans += left_dp[d][i].ff*right_dp[d][i].ss; ans %= MOD; ans += left_dp[d][i].ss*right_dp[d][i].ff; ans %= MOD; } } cout << ans << "\n"; }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...