题号 | 标题 | 已通过代码 | 题解/讨论 | 通过率 | 团队的状态 |
---|---|---|---|---|---|
A | String | 点击查看 | 进入讨论 | 566/3539 | 通过 |
B | Irreducible Polynomial | 点击查看 | 规律 | 730/2290 | 未通过 |
C | Governing sand | 点击查看 | 进入讨论 | 388/2088 | 通过 |
D | Number | 点击查看 | 进入讨论 | 959/1469 | 通过 |
E | Find the median | 点击查看 | 离散化 | 88/985 | OK |
F | Energy stones | 点击查看 | BIT | 16/132 | 未通过 |
G | Make Shan Happy | 点击查看 | 进入讨论 | 3/29 | 未通过 |
H | Pair | 点击查看 | 数位DP | 93/245 | OK |
I | Chessboard | 点击查看 | 进入讨论 | 17/83 | 未通过 |
J | A+B problem | 点击查看 | 进入讨论 | 1024/1844 | 通过 |
K | Function | 点击查看 | 进入讨论 | 8/49 | 未通过 |
E-Find the median
题意
n次操作,($n le 400000$),每次给出$L_i, R_i$向集合中插入,让你把$[L_i, L_i+1, L_i+2, ... , R_i]$ 插入到集合中,同时输出集合的中位数。
集合一开始为空,($1 le L_i, R[i] le 1e9$)
思路
空间有限,所以不可以把两个端点间的一段单独拿出来当成一个点
动态开点也被卡了空间
具体思路还是离散化,我们可以中间的点和左端点看成一个点
把原来对闭区间的操作改为对左闭右开区间的操作
就是把原来的$[L_i, R_i]$ 更改为 $[L_i, R_i + 1)$
// #pragma GCC optimize(2) // #pragma GCC optimize(3) // #pragma GCC optimize(4) #include <algorithm> #include <iterator> #include <iostream> #include <cstring> #include <cstdlib> #include <iomanip> #include <bitset> #include <cctype> #include <cstdio> #include <string> #include <vector> #include <stack> #include <cmath> #include <queue> #include <list> #include <map> #include <set> #include <cassert> // #include<bits/extc++.h> // using namespace __gnu_pbds; using namespace std; #define pb push_back #define fi first #define se second #define debug(x) cerr<<#x << " := " << x << endl; #define bug cerr<<"-----------------------"<<endl; #define FOR(a, b, c) for(int a = b; a <= c; ++ a) typedef long long ll; typedef long double ld; typedef pair<int, int> pii; typedef pair<ll, ll> pll; const int inf = 0x3f3f3f3f; const ll inff = 0x3f3f3f3f3f3f3f3f; const int mod = 1e9+7; template<typename T> inline T read(T&x){ x=0;int f=0;char ch=getchar(); while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar(); while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar(); return x=f?-x:x; } /**********showtime************/ const int big = 1e9; const int maxn = 400005; int X[maxn],Y[maxn]; int L[maxn], R[maxn]; int a1,b1,c1,m1; int a2,b2,c2,m2; struct node{ int cnt; ll sum; int lazy; int len; } tree[maxn * 8]; //离散化 vector<int>vec; int getid(int x) { return lower_bound(vec.begin(), vec.end(), x) - vec.begin() + 1; } // void pushdown(int le,int ri,int rt) { tree[rt<<1].cnt += tree[rt].lazy; tree[rt<<1|1].cnt += tree[rt].lazy; tree[rt<<1].lazy += tree[rt].lazy; tree[rt<<1|1].lazy += tree[rt].lazy; int mid = (le + ri) >> 1; tree[rt<<1].sum += 1ll*tree[rt].lazy * (vec[mid] - vec[le-1]); tree[rt<<1|1].sum += 1ll*tree[rt].lazy *(vec[ri] - vec[mid]); tree[rt].lazy = 0; } void update(int L, int R, int le, int ri, int rt) { if(le >= L && ri <= R) { tree[rt].lazy++; tree[rt].cnt++; //因为每个节点表示【le实际值,ri实际值)的长度。 tree[rt].sum += 1ll*(vec[ri] - vec[le - 1]); return; } int mid = (le + ri) >> 1; if(tree[rt].lazy) pushdown(le,ri,rt); if(mid >= L) { update(L, R, le, mid, rt<<1); } if(mid < R) { update(L, R, mid+1, ri, rt<<1|1); } tree[rt].sum = tree[rt<<1].sum + tree[rt<<1|1].sum; } int query(ll tot, int le, int ri, int rt) { if(le == ri) { int cnt = tree[rt].cnt, res; int lbound = vec[le-1]; if(tot % cnt == 0) { res = lbound + tot / cnt - 1; } else res = lbound + tot / cnt; return res; } int mid = (le + ri) >> 1; if(tree[rt].lazy) pushdown(le,ri,rt); ll lsum = tree[rt<<1].sum; if(lsum >= tot) return query(tot,le, mid, rt<<1); else return query(tot - lsum, mid+1, ri, rt<<1|1); } int main(){ int n; scanf("%d", &n); scanf("%d%d%d%d%d%d", &X[1], &X[2], &a1, &b1, &c1, &m1); scanf("%d%d%d%d%d%d", &Y[1], &Y[2], &a2, &b2, &c2, &m2); L[1] = min(X[1], Y[1]) + 1; R[1] = max(X[1], Y[1]) + 1; L[2] = min(X[2], Y[2]) + 1; R[2] = max(X[2], Y[2]) + 1; //因为我后面操作的是左闭右开区间,所以这里右端点++。 R[1] ++; R[2] ++; vec.pb(L[1]);vec.pb(R[1] ); vec.pb(L[2]);vec.pb(R[2]); for(int i=3; i<=n; i++) { X[i] = (1ll*a1 * X[i-1] + 1ll*b1 * X[i-2] + c1 )% m1; Y[i] = (1ll*a2 * Y[i-1] + 1ll*b2 * Y[i-2] + c2 )% m2; L[i] = min(X[i], Y[i]) + 1; R[i] = max(X[i], Y[i]) + 1; R[i] ++; vec.pb(L[i]); vec.pb(R[i]); } sort(vec.begin(), vec.end()); vec.erase(unique(vec.begin(), vec.end()), vec.end()); for(int i=1; i<=n; i++) { L[i] = getid(L[i]); R[i] = getid(R[i]); } int tot = vec.size(); ll all = 0; for(int i=1; i<=n; i++) { update(L[i], R[i] - 1, 1, tot, 1); all += 1ll*(vec[R[i]-1] - vec[L[i] - 1]); printf("%d ", query((all + 1)/2, 1, tot, 1)); } return 0; }
H Pair
题意
给定A,B,C($A le 1e9, B le 1e9, C le 1e9$),求满足
$$ (x & y) > C $$
$$ (x oplus y) < C$$
的<x, y>对数。其中
$ 1 le x le A, 1 le y le B$
思路
数位DP,自己code了好久
/* * @Author: chenkexing * @Date: 2019-08-09 23:58:00 * @Last Modified by: chenkexing * @Last Modified time: 2019-08-10 22:19:16 * @Link https://ac.nowcoder.com/acm/contest/887/H */ // #pragma GCC optimize(2) // #pragma GCC optimize(3) // #pragma GCC optimize(4) #include <algorithm> #include <iterator> #include <iostream> #include <cstring> #include <cstdlib> #include <iomanip> #include <bitset> #include <cctype> #include <cstdio> #include <string> #include <vector> #include <stack> #include <cmath> #include <queue> #include <list> #include <map> #include <set> #include <cassert> // #include<bits/extc++.h> // using namespace __gnu_pbds; using namespace std; #define pb push_back #define fi first #define se second #define debug(x) cerr<<#x << " := " << x << endl; #define bug cerr<<"-----------------------"<<endl; #define FOR(a, b, c) for(int a = b; a <= c; ++ a) typedef long long ll; typedef long double ld; typedef pair<int, int> pii; typedef pair<ll, ll> pll; const int inf = 0x3f3f3f3f; const ll inff = 0x3f3f3f3f3f3f3f3f; const int mod = 1e9+7; template<typename T> inline T read(T&x){ x=0;int f=0;char ch=getchar(); while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar(); while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar(); return x=f?-x:x; } /**********showtime************/ ll dp[35][2][2][2][2][3][3]; //dp[len][limit1][limit2][ok1][ok2] //由于两个数要大于0,所以多加上ok1,ok2. //f1 &的, f2 ^的 // == 2 表示不行了 int shuA[35],shuB[35],shuC[35]; ll dfs(int len, int limit1, int limit2, int ok1, int ok2, int f1, int f2){ if(f1 == 2 && f2 == 2) return 0; if(dp[len][limit1][limit2][ok1][ok2][f1][f2] != -1) return dp[len][limit1][limit2][ok1][ok2][f1][f2]; if(len == 0) { return ok1 && ok2 && (f1 == 1 || f2 == 1); } int up1 = 1, up2 = 1; if(limit1) up1 = shuA[len]; if(limit2) up2 = shuB[len]; ll res = 0; // cout<<len<<" " << up1<<" , " << up2<<endl; for(int i=0; i<=up1; i++) { for(int j=0; j<=up2; j++) { // if(len == 2)cout<<len << " " << i << " , " << j << " = " << f1 <<" , , " <<f2 << endl; if(f1 == 1 || f2 == 1) res += dfs(len-1, limit1 && i == up1, limit2 && j == up2, ok1 || i, ok2 || j, f1, f2); else { int F1 = f1, F2 = f2; if((i & j) < shuC[len]) F1 = 2; else if((i & j) > shuC[len]) F1 = max(F1, 1); if((i ^ j) > shuC[len]) F2 = 2; else if((i ^ j) < shuC[len]) F2 = max(F2, 1); res += dfs(len-1, limit1 && i == up1, limit2 && j == up2, ok1 || i, ok2 || j, F1, F2); } } } dp[len][limit1][limit2][ok1][ok2][f1][f2] = res; return res; } int main(){ int T; scanf("%d", &T); while(T--) { int a, b, c; scanf("%d%d%d", &a, &b, &c); memset(dp, -1, sizeof(dp)); int len = 32; for(int i=1; i<=len; i++) shuA[i] = a % 2, a = a >> 1; for(int i=1; i<=len; i++) shuB[i] = b % 2, b = b >> 1; for(int i=1; i<=len; i++) shuC[i] = c % 2, c = c >> 1; printf("%lld ", dfs(len, 1, 1, 0, 0, 0, 0)); } return 0; }