Solved | Pro.ID | Title | Ratio(Accepted / Submitted) |
1001 | Salty Fish | 16.28%(7/43) | |
OK | 1002 | Nonsense Time 暴力 | 7.88%(57/723) |
1003 | Milk Candy | 12.90%(4/31) | |
1004 | Speed Dog | 26.97%(48/178) | |
1005 | Snowy Smile | 8.52%(225/2640) | |
1006 | Faraway | 27.92%(98/351) | |
1007 | Support or Not | 8.33%(3/36) | |
1008 | TDL | 27.63%(921/3333) | |
1009 | Three Investigators | 7.14%(1/14) | |
1010 | Ridiculous Netizens 点分治 | 38.71%(24/62) | |
1011 | 11 Dimensions | 13.47%(64/475) | |
1012 | Stay Real | 45.04%(1044/2318) |
1002 Nonsense Time
题意
给定一个长度n($n le 50000$)的排列$p_1, p_2, ... ,p_n$,给定一个长度为n的排列$a_1, a_2, ... ,a_n$.
初始排列p是不可见的,从1到n,第$p_{a_i}$个可见,输出此时可见p的LIS。
数据保证纯随机。
思路
由于是随机,所以有人证明lis的期望是O($sqrt{n}$)。
所以我们利用时间倒流技术,从后往前做。
记录一个LIS,如果要删除的数是LIS上的,就重新算一个LIS,如果要删的数不再LIS上,那什么事也没发生。
复杂度 = $ n imes lgroup frac{1}{sqrt{n}} imes n imes log n + frac{1}{sqrt{n}} group$
= $n imes sqrt{n} imes log n + sqrt{n}$
// #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 maxn = 50009; int p[maxn],a[maxn]; int vis[maxn],used[maxn], ans[maxn]; int que[maxn], dp[maxn]; int n; int solve() { int len = 0; for(int i=1; i<=n; i++) { used[i] = 0; if(vis[i]) continue; int pos = lower_bound(que+1, que+1+len, p[i]) - que; if(pos > len) { que[++len] = p[i]; dp[i] = len; } else { que[pos] = p[i]; dp[i] = pos; } // for(int i=1; i<=len; i++) cout<<que[i]<<" "; // cout<<endl; } int res = len; for(int i=n; i>=1; i--) { if(vis[i]) continue; if(dp[i] == len) { used[i] = 1; len--; } } return res; } int main(){ int T; scanf("%d", &T); while(T--) { scanf("%d", &n); for(int i=1; i<=n; i++) scanf("%d", &p[i]); for(int i=1; i<=n; i++) scanf("%d", &a[i]); for(int i=1; i<=n; i++) vis[i] = 0; int cur = solve(); for(int i=n; i>=1; i--) { ans[i] = cur; vis[a[i]] = 1; if(used[a[i]] != 0) { cur = solve(); } } for(int i=1; i<n; i++) printf("%d ", ans[i]); printf("%d ", ans[n]); } return 0; }
1011 11 Dimensions
我自己用DP1A了,好像还有康托展开的方法,可以搞搞
// #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 maxn = 5e4+9; ll big = 1e18; ll dp[maxn][22]; ll md[maxn],mdd[maxn]; char str[maxn]; vector<int>vec; int main(){ md[0] = 1; for(int i=1; i<maxn; i++) md[i] = md[i-1] * 10 % mod; int T; scanf("%d", &T); while(T--) { int n,m,q; scanf("%d%d%d", &n, &m, &q); mdd[0] = 1; for(int i=1; i<maxn; i++) mdd[i] = mdd[i-1] * 10 % m; scanf("%s", str+1); ll sum = 0, tp = 0; vec.clear(); for(int i=0; i<=n; i++) { for(int j=0; j<m; j++) dp[i][j] = 0; } for(int i=n; i>=1; i--) { if(str[i] == '?') { if(vec.size() < 25) vec.pb(i); } else { sum = (sum + md[n-i] * (str[i] - '0') % mod) % mod; tp = (tp + mdd[n-i] * (str[i] - '0') % m) % m; } } dp[0][tp] = 1; int all = vec.size(); for(int i=1; i<=all; i++) { int id = vec[i-1]; for(int j=0; j<10; j++) { int up = mdd[n - id] * j % m; for(int k=0; k<m; k++) { ll tmp = dp[i][k] + dp[i - 1][(k - up + m) % m]; if(tmp <= big) { dp[i][k] = tmp; } else dp[i][k] = big+1; } } } while(q--) { ll cur = sum; int flag = 1; int y = 0; ll k; scanf("%lld", &k); k--; for(int i=all; i>=1; i--) { int id = vec[i-1]; int flag = 1; for(int j=0; j<10; j++) { int tmp = (y + j * mdd[n-id] % m) % m; if(dp[i-1][(m - tmp) % m] > k) { y = tmp; cur = (cur + j * md[n-id] % mod) % mod; flag = 0; break; } else { k -= dp[i-1][(m - tmp) % m]; } } if(flag) {k=1; break;} } if(k) puts("-1"); else printf("%lld ", cur); } } return 0; }