咕值详见去年多校
牛客
题号 | 标题 | 团队的状态 |
---|---|---|
A | Equivalent Prefixes | 通过 |
B | Integration | 通过 |
C | Euclidean Distance | 通过 |
D | Parity of Tuples | 未通过 |
E | ABBA | 通过 |
F | Random Point in Triangle | 通过 |
G | Substrings 2 | 未通过 |
H | XOR | 通过 |
I | Points Division | 通过 |
J | Fraction Comparision | 通过 |
A
思路:二分+单调栈
代码:
#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include<bits/stdc++.h> using namespace std; #define y1 y11 #define fi first #define se second #define pi acos(-1.0) #define LL long long //#define mp make_pair #define pb emplace_back #define ls rt<<1, l, m #define rs rt<<1|1, m+1, r #define ULL unsigned LL #define pll pair<LL, LL> #define pli pair<LL, int> #define pii pair<int, int> #define piii pair<pii, int> #define pdd pair<double, double> #define mem(a, b) memset(a, b, sizeof(a)) #define debug(x) cerr << #x << " = " << x << "\n"; #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); //head const int N = 1e5 + 5; int n, a[N], b[N], la[N], ra[N],lb[N], rb[N]; stack<int> st; inline bool ck(int m) { while(!st.empty()) st.pop(); st.push(0); for (int i = 1; i <= m; ++i) { while(!st.size() > 1 && a[st.top()] > a[i]) st.pop(); la[i] = st.top(); st.push(i); } while(!st.empty()) st.pop(); st.push(m+1); for (int i = m; i >= 1; --i) { while(st.size() > 1 && a[st.top()] > a[i]) st.pop(); ra[i] = st.top(); st.push(i); } while(!st.empty()) st.pop(); st.push(0); for (int i = 1; i <= m; ++i) { while(!st.size() > 1 && b[st.top()] > b[i]) st.pop(); lb[i] = st.top(); st.push(i); } while(!st.empty()) st.pop(); st.push(m+1); for (int i = m; i >= 1; --i) { while(st.size() > 1 && b[st.top()] > b[i]) st.pop(); rb[i] = st.top(); st.push(i); } for (int i = 1; i <= m; ++i) if(la[i] != lb[i] || ra[i] != rb[i]) return false; return true; } int main() { while(~scanf("%d", &n)) { for (int i = 1; i <= n; ++i) scanf("%d", &a[i]); for (int i = 1; i <= n; ++i) scanf("%d", &b[i]); int l = 1, r = n, m = l+r+1 >>1; while( l < r) { if(ck(m)) l = m; else r = m-1; m = l+r+1>>1; } printf("%d\n", m); } return 0; }
B
思路:裂项,详见D神博客
代码:
#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include<bits/stdc++.h> using namespace std; #define y1 y11 #define fi first #define se second #define pi acos(-1.0) #define LL long long //#define mp make_pair #define pb push_back #define ls rt<<1, l, m #define rs rt<<1|1, m+1, r #define ULL unsigned LL #define pll pair<LL, LL> #define pli pair<LL, int> #define pii pair<int, int> #define piii pair<pii, int> #define pdd pair<double, double> #define mem(a, b) memset(a, b, sizeof(a)) #define debug(x) cerr << #x << " = " << x << "\n"; #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); //head const int N = 1e3 + 5; const int MOD = 1e9 + 7; int a[N], n; LL q_pow(LL n, LL k) { LL ans = 1; while(k){ if(k&1) ans = (ans * n) % MOD; n =(n * n) % MOD; k >>= 1; } return ans; } int main() { while(~scanf("%d", &n)) { for (int i = 1; i <= n; ++i) scanf("%d",&a[i]); LL ans = 0; for (int i = 1; i <= n; ++i) { LL tmp = 2*a[i]%MOD; for (int j = 1; j <= n; ++j) { if(i == j) continue; tmp = (tmp * (a[j]*1LL*a[j]%MOD-a[i]*1LL*a[i]%MOD))%MOD; } ans = (ans + q_pow(tmp, MOD-2))%MOD; } printf("%lld\n", (ans+MOD)%MOD); } return 0; }
C
思路:贪心,从大到小推平。详见大佬博客
代码:
#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include<bits/stdc++.h> using namespace std; #define y1 y11 #define fi first #define se second #define pi acos(-1.0) #define LL long long //#define mp make_pair #define pb push_back #define ls rt<<1, l, m #define rs rt<<1|1, m+1, r #define ULL unsigned LL #define pll pair<LL, LL> #define pli pair<LL, int> #define pii pair<int, int> #define piii pair<pii, int> #define pdd pair<double, double> #define mem(a, b) memset(a, b, sizeof(a)) #define debug(x) cerr << #x << " = " << x << "\n"; #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); //head const int N = 1e4 + 5; int a[N], sum[N], n, m; int main() { while(~scanf("%d %d", &n, &m)) { for (int i = 1; i <= n; ++i) scanf("%d", &a[i]); sort(a+1, a+1+n, greater<int>()); for (int i = 1; i <= n; ++i) sum[i] = sum[i-1]+a[i]; int pos = n+1; LL x=0, y=0; for (int i = 1; i <= n; ++i){ if(sum[i]-a[i]*i <= m) { x = (sum[i]-m)*1LL*(sum[i]-m)*i; y = i*i; } else { pos = i; break; } } for (int i = pos; i <= n; ++i) x += a[i]*1LL*a[i]*y; y *= m*m; LL d = __gcd(x, y); if(d) x /= d, y /= d; if(x == 0) printf("0\n"); else if(y == 1) printf("%lld\n", x); else printf("%lld/%lld\n", x, y); } return 0; }
D
E
思路:dp,保证A和B的差值在$-m$到$+n$之间
代码:
#include <bits/stdc++.h> 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; template<class T> void _R(T &x) { cin >> x; } void _R(int &x) { scanf("%d", &x); } void _R(ll &x) { scanf("%lld", &x); } void _R(double &x) { scanf("%lf", &x); } void _R(char &x) { scanf(" %c", &x); } void _R(char *x) { scanf("%s", x); } void R() {} template<class T, class... U> void R(T &head, U &... tail) { _R(head); R(tail...); } 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; } const int inf = 0x3f3f3f3f; const int mod = 1e9+7; /**********showtime************/ const int maxn = 8e3+9; ll dp[maxn][maxn]; int g(int x) { return x + 4000; } int main(){ int n,m; while(~scanf("%d%d", &n, &m)) { int s = 2 * (n + m); int t = (n + m); for(int i=0; i<=s; i++) { for(int j=-t; j<=t; j++) { dp[i][g(j)] = 0; } } dp[0][g(0)] = 1; for(int i=1; i<=s; i++) { for(int j=-t; j<=t; j++) { if(j <= n) dp[i][g(j)] = (dp[i][g(j)] + dp[i-1][g(j-1)] ) %mod; if(j >= -m) dp[i][g(j)] = (dp[i][g(j)] + dp[i-1][g(j+1)] ) %mod; } } // cout<<dp[s][g(0)]<<endl; printf("%lld\n", dp[s][g(0)]); } return 0; }
F
思路:
$\frac{22*s}{36}$
代码:
#include<bits/stdc++.h> #define ll long long using namespace std; struct Point { // double pan duan ll x,y; Point(ll a=0,ll b=0) { x=a;y=b; }; }; typedef Point Vector; Vector operator + (Vector A, Vector B){ return Vector(A.x+B.x, A.y+B.y); } // 向量相加 Vector operator - (Point A, Point B){ return Vector(A.x-B.x, A.y-B.y); } // 向量生成 double operator * (Vector A, Vector B){ return A.x*B.x-A.y*B.y; } // 点积 double operator ^ (Vector A, Vector B){ return A.x*B.y-A.y*B.x; } // 叉积 ll Cross(Vector A, Vector B) { return A.x*B.y - A.y*B.x; } // 叉积 ll Area2(Point A, Point B, Point C) { return Cross(B-A, C-A); } // 四边形面积 int main(){ Point a,b,c; while(~scanf("%lld %lld %lld %lld %lld %lld",&a.x,&a.y,&b.x,&b.y,&c.x,&c.y)){ ll area=abs(Cross(b-a,c-a) ) *11; printf("%lld\n",area); } }
G
H
思路:线性基。
先将问题转换成包含某个元素的异或起来为0的集合个数和
首先,先选出一组基(假设大小为$r$),那么对于非基元素的任意组合都可由基线性表示,也就是说对于每个非基元素,有$2^{n-r-1}$个包含它的集合满足题意,
这部分贡献是$(n-r)*2^{n-r-1}$。
然后考虑包含基元素的满足题意的集合个数,对于某个基元素,将剩下的$n-1$个元素构成一组基,看能不能线性表示出它,如果能,包含这个基元素的集合个数是$2^{剩下元素个数}$
对于第二种情况可以先处理出非基元素的一组基。
代码:
#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include<bits/stdc++.h> using namespace std; #define y1 y11 #define fi first #define se second #define pi acos(-1.0) #define LL long long //#define mp make_pair #define pb push_back #define ls rt<<1, l, m #define rs rt<<1|1, m+1, r #define ULL unsigned LL #define pll pair<LL, LL> #define pli pair<LL, int> #define pii pair<int, int> #define piii pair<pii, int> #define pdd pair<double, double> #define mem(a, b) memset(a, b, sizeof(a)) #define debug(x) cerr << #x << " = " << x << "\n"; #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); //head const int N = 1e5 + 5; const int MOD = 1e9 + 7; int n; LL a[N]; vector<LL> s, b, other, B; LL q_pow(LL n, LL k) { if(k < 0) return 0; LL res = 1; while(k) { if(k&1) res = (res*n)%MOD; n = (n*n)%MOD; k >>= 1; } return res; } int main() { while(~scanf("%d", &n)) { s.clear();b.clear();other.clear();B.clear(); for (int i = 1; i <= n; ++i) scanf("%lld", &a[i]); for (int i = 1; i <= n; ++i) { LL t = a[i]; for (LL x : b) { if((t^x) < t) t ^= x; } if(t) b.pb(t), s.pb(a[i]); else other.pb(a[i]); } int sz = b.size(); LL ans = (n-sz)*q_pow(2, n-sz-1)%MOD; for (LL x : other) { for (LL t : B) { if((x^t) < x) x ^= t; } if(x) B.pb(x); } for (LL x : s) { vector<LL> tb = B; for (LL t : s) { if(t != x) { for (LL y : tb) { if((y^t) < t) t ^= y; } if(t) tb.pb(t); } } for (LL t : tb) { if((x^t) < x) x ^= t; } if(!x) ans = (ans + q_pow(2, n-tb.size()-1))%MOD; } printf("%lld\n", ans); } return 0; }
I
思路:线段树优化dp。
首先根据题意,A和B集合的分界线肯定是一横一竖交替出现的折线。那么考虑以每个点i为折线的转折点时的dp[i]。用线段树维护之前转折点的最大值并更新以当前点为转折点的最大值。
对于每个点i,它对y值为[0, a[i].y-1]转折点的贡献为a,对y值为[a[i].y+1,len]转折点的贡献为b。因为a集合在上,b集合在下。
代码:
#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include<bits/stdc++.h> using namespace std; #define y1 y11 #define fi first #define se second #define pi acos(-1.0) #define LL long long //#define mp make_pair #define pb emplace_back #define ls rt<<1, l, m #define rs rt<<1|1, m+1, r #define ULL unsigned LL #define pll pair<LL, LL> #define pli pair<LL, int> #define pii pair<int, int> #define piii pair<pii, int> #define pdd pair<double, double> #define mem(a, b) memset(a, b, sizeof(a)) #define debug(x) cerr << #x << " = " << x << "\n"; #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); //head const int N = 1e5 + 5; struct Node { int x, y, a, b; bool operator < (const Node & rhs) const { if(x == rhs.x) return y > rhs.y; else return x < rhs.x; } }a[N]; int n; vector<int> vc; LL mx[N<<2], lazy[N<<2]; inline void push_up(int rt) { mx[rt] = max(mx[rt<<1], mx[rt<<1|1]); } inline void push_down(int rt) { lazy[rt<<1] += lazy[rt]; lazy[rt<<1|1] += lazy[rt]; mx[rt<<1] += lazy[rt]; mx[rt<<1|1] += lazy[rt]; lazy[rt] = 0; } void build(int rt, int l, int r) { mx[rt] = lazy[rt] = 0; if(l == r) return ; int m = l+r >> 1; build(ls); build(rs); push_up(rt); } void update(int p, LL v, int rt, int l, int r) { if(l == r){ mx[rt] = v; return ; } int m = l+r >> 1; if(lazy[rt]) push_down(rt); if(p <= m) update(p, v, ls); else update(p, v, rs); push_up(rt); } void Update(int L, int R, int v, int rt, int l, int r) { if(L > R) return ; if(L <= l && r <= R) { mx[rt] += v; lazy[rt] += v; return ; } int m = l+r >> 1; if(lazy[rt]) push_down(rt); if(L <= m) Update(L, R, v, ls); if(R > m) Update(L, R, v, rs); push_up(rt); } LL query(int L, int R, int rt, int l, int r){ if(L > R) return 0; if(L <= l && r <= R) return mx[rt]; int m = l+r >> 1; if(lazy[rt]) push_down(rt); LL ans = 0; if(L <= m) ans = max(ans, query(L, R, ls)); if(R > m) ans = max(ans, query(L, R, rs)); push_up(rt); return ans; } int main() { while(~scanf("%d", &n)) { vc.clear(); for (int i = 1; i <= n; ++i) scanf("%d %d %d %d",&a[i].x, &a[i].y, &a[i].a, &a[i].b), vc.pb(a[i].y); sort(vc.begin(), vc.end()); vc.erase(unique(vc.begin(), vc.end()), vc.end()); for (int i = 1; i <= n; ++i) a[i].y = lower_bound(vc.begin(), vc.end(), a[i].y)-vc.begin()+1; sort(a+1, a+1+n); int l = vc.size(); ++l; build(1, 0, l); for (int i = 1; i <= n; ++i) { LL tmp = query(0, a[i].y, 1, 0, l); update(a[i].y, tmp+a[i].b, 1, 0, l); Update(0, a[i].y-1, a[i].a, 1, 0, l); Update(a[i].y+1, l, a[i].b, 1, 0, l); } printf("%lld\n", mx[1]); } return 0; } /* 3 1 1 10 1 8 9 10 1 5 4 10 1 */
J
思路:大数过
import java.math.BigInteger; import java.util.*; public class Main { /** * @param args */ public static void main(String[] args) { BigInteger x, a, y, b; Scanner reader = new Scanner(System.in); while(reader.hasNext()) { x = reader.nextBigInteger(); a = reader.nextBigInteger(); y = reader.nextBigInteger(); b = reader.nextBigInteger(); if(x.multiply(b).compareTo(y.multiply(a)) == 0) { System.out.println("="); } else if(x.multiply(b).compareTo(y.multiply(a)) > 0) { System.out.println(">"); } else { System.out.println("<"); } } } }
题号 | 标题 | 团队的状态 |
---|---|---|
A | Eddy Walker | 通过 |
B | Eddy Walker 2 | 通过 |
C | Go on Strike! | 未通过 |
D | Kth Minimum Clique | 通过 |
E | MAZE | 通过 |
F | Partition problem | 通过 |
G | Polygons | 通过 |
H | Second Large Rectangle | 通过 |
I | Inside A Rectangle | 未通过 |
J | Subarray | 通过 |
A
思路:蒙特卡洛一下,就能找到规律,除了0这个点,其他点的概率是$\frac{1}{n-1}$,队友读了题居然没跟我说题意,血亏。
以n=10为例,打表代码:
#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include<bits/stdc++.h> using namespace std; #define ll long long #define pb push_back int a[10]; int main() { mt19937 mt_rand(time(NULL)); for (int i = 1; i <= 100000; ++i) { int st = 0; int up = 1<<10, s = 1; while(true) { if(mt_rand()%2 == 0) st = (st+9)%10; else st = (st+1)%10; s |= 1<< st; if(s == up-1) { a[st]++; break; } } } for (int i = 0; i < 10; ++i) printf("%d %.10f\n", i, a[i]*1.0/100000); return 0; }
代码:
#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include<bits/stdc++.h> using namespace std; #define LL long long #define pb push_back const int MOD = 1e9 + 7; int T, m, n; LL q_pow(LL n, LL k) { LL res = 1; while(k) { if(k&1) res = (res*n) % MOD; n = (n * n)%MOD; k >>= 1; } return res; } int main() { scanf("%d", &T); LL res = 1; while(T--) { scanf("%d %d", &n, &m); if(n == 1) ; else if(m) (res *= q_pow(n-1, MOD-2)) %= MOD; else res *= 0; printf("%lld\n", res); } return 0; }
B
思路:容易发现是个线性递推式,因为系数$\frac{1}{k}$是个常数。于是可以打出前2*k项,扔进杜教BM板子里就能求出第$n$项。
代码:
#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include<bits/stdc++.h> using namespace std; #define ll long long #define pb push_back const int mod = 1e9 + 7; const int MOD = 1e9 + 7; ll q_pow(ll n, ll k) { ll res = 1; while(k) { if(k&1) res = (res*n)%mod; n = (n*n)%mod; k >>= 1; } return res; } namespace linear_seq { const int N=10010; #define rep(i,a,n) for (int i=a;i<n;i++) #define per(i,a,n) for (int i=n-1;i>=a;i--) #define mp make_pair #define all(x) (x).begin(),(x).end() #define SZ(x) ((int)(x).size()) typedef vector<ll> VI; typedef pair<ll,ll> PII; ll powmod(ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;} ll res[N],base[N],_c[N],_md[N]; vector<ll> Md; void mul(ll *a,ll *b,int k) { rep(i,0,k+k) _c[i]=0; rep(i,0,k) if (a[i]) rep(j,0,k) _c[i+j]=(_c[i+j]+a[i]*b[j])%mod; for (int i=k+k-1;i>=k;i--) if (_c[i]) rep(j,0,SZ(Md)) _c[i-k+Md[j]]=(_c[i-k+Md[j]]-_c[i]*_md[Md[j]])%mod; rep(i,0,k) a[i]=_c[i]; } ll solve(ll n,VI a,VI b) { // a 系数 b 初值 b[n+1]=a[0]*b[n]+... // printf("%d\n",SZ(b)); ll ans=0,pnt=0; int k=SZ(a); assert(SZ(a)==SZ(b)); rep(i,0,k) _md[k-1-i]=-a[i];_md[k]=1; Md.clear(); rep(i,0,k) if (_md[i]!=0) Md.push_back(i); rep(i,0,k) res[i]=base[i]=0; res[0]=1; while ((1ll<<pnt)<=n) pnt++; for (int p=pnt;p>=0;p--) { mul(res,res,k); if ((n>>p)&1) { for (int i=k-1;i>=0;i--) res[i+1]=res[i];res[0]=0; rep(j,0,SZ(Md)) res[Md[j]]=(res[Md[j]]-res[k]*_md[Md[j]])%mod; } } rep(i,0,k) ans=(ans+res[i]*b[i])%mod; if (ans<0) ans+=mod; return ans; } VI BM(VI s) { VI C(1,1),B(1,1); int L=0,m=1,b=1; rep(n,0,SZ(s)) { ll d=0; rep(i,0,L+1) d=(d+(ll)C[i]*s[n-i])%mod; if (d==0) ++m; else if (2*L<=n) { VI T=C; ll c=mod-d*powmod(b,mod-2)%mod; while (SZ(C)<SZ(B)+m) C.pb(0); rep(i,0,SZ(B)) C[i+m]=(C[i+m]+c*B[i])%mod; L=n+1-L; B=T; b=d; m=1; } else { ll c=mod-d*powmod(b,mod-2)%mod; while (SZ(C)<SZ(B)+m) C.pb(0); rep(i,0,SZ(B)) C[i+m]=(C[i+m]+c*B[i])%mod; ++m; } } return C; } ll gao(VI a,ll n) { VI c=BM(a); c.erase(c.begin()); rep(i,0,SZ(c)) c[i]=(mod-c[i])%mod; return solve(n,c,VI(a.begin(),a.begin()+SZ(c))); } }; int k, T; ll n; int main() { scanf("%d", &T); while(T--) { scanf("%d %lld", &k, &n); vector<ll> vc; if(n == -1) printf("%lld\n", 2*q_pow(k+1, MOD-2)%MOD); else { vc.pb(1); for (int i = 1; i <= 2*k; ++i) { ll tmp = 0; for (int j = max(0, i-k); j < i; ++j){ (tmp += vc[j]) %= MOD; } (tmp *= q_pow(k, MOD-2)) %= MOD; vc.pb(tmp); } printf("%lld\n", linear_seq::gao(vc, n)); } } return 0; }
C
D
思路:
既然要选择第K小的,我们可以从小到大做。每次通过最小的一个最小团扩展,可以利用bitset优化判断扩展的可行性。利用优先队列,从其中取出的第k个就是答案。
队友代码:
#include<bits/stdc++.h> 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; template<class T> void _R(T &x) { cin >> x; } void _R(int &x) { scanf("%d", &x); } void _R(ll &x) { scanf("%lld", &x); } void _R(double &x) { scanf("%lf", &x); } void _R(char &x) { scanf(" %c", &x); } void _R(char *x) { scanf("%s", x); } void R() {} template<class T, class... U> void R(T &head, U &... tail) { _R(head); R(tail...); } 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; } const int inf = 0x3f3f3f3f; const int mod = 1e9+7; /**********showtime************/ const int maxn = 109; char str[maxn]; struct node{ ll val; bitset<109>bs; bool operator<(const node & o) const{ return val > o.val; } }a[maxn]; int main(){ int n,k; scanf("%d%d", &n, &k); for(int i=1; i<=n; i++) { scanf("%lld", &a[i].val); } for(int i=1; i<=n; i++) { scanf("%s", str+1); for(int j=1; j<=n; j++) { if(str[j] == \'1\')a[i].bs.set(j); } } priority_queue<node>que; node s; s.val = 0; s.bs.reset(); que.push(s); int flag = 0;ll res; while(!que.empty()) { node u = que.top(); que.pop(); k -- ; if(k == 0) { flag = 1; res = u.val; break; } int mx = 1; for(int i=1; i<=n; i++) { if(u.bs[i] == 1) mx = i + 1; } for(int i=mx; i<=n; i++) { if((u.bs & a[i].bs) == u.bs) { u.bs.set(i); u.val += a[i].val; que.push(u); u.bs.reset(i); u.val -= a[i].val; } } } if(flag) printf("%lld\n", res); else puts("-1"); return 0; }
E
思路:
考虑从第$i$行到第$i+1$行的转移,假设第$i$行为"10010"
设 $dp_{i,j}$表示到第$i$行第$j$列的方案数。
于是相邻两项dp的转移过程可以看成一个矩阵乘以一个向量(如果暂时不考虑当前行的横向转移)。 多项之间的转移可以看成矩阵连乘再乘以一个向量。
于是用线段树维护矩阵的乘法,线段树每个叶子节点表示一个矩阵。 单次修改复杂度O($log(n)m^3$),其中$m^3$是矩阵乘法的复杂度。
代码:
#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include<bits/stdc++.h> using namespace std; #define y1 y11 #define fi first #define se second #define pi acos(-1.0) #define LL long long //#define mp make_pair #define pb emplace_back #define ls rt<<1, l, m #define rs rt<<1|1, m+1, r #define ULL unsigned LL #define pll pair<LL, LL> #define pli pair<LL, int> #define pii pair<int, int> #define piii pair<pii, int> #define pdd pair<double, double> #define mem(a, b) memset(a, b, sizeof(a)) #define debug(x) cerr << #x << " = " << x << "\n"; #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); //head const int N = 5e4 + 5; const int MOD = 1e9 + 7; int n, q, m, op, x, y; string b[N]; struct Matrix { int a[10][10]; inline void init() {memset(a, 0, sizeof a);} inline void _init() { init(); for (int i = 0; i < m; ++i) a[i][i] = 1; } inline void reset(int p) { init(); for (int i = 0; i < m; ++i) { for (int j = i; j >= 0; --j) if(b[p][j] == \'0\') a[j][i] = 1; else break; for (int j = i; j < m; ++j) if(b[p][j] == \'0\') a[j][i] = 1; else break; } } inline Matrix operator * (const Matrix & rhs) const { Matrix res; res.init(); for (int i = 0; i < m; ++i) { for (int j = 0; j < m; ++j) { if(a[i][j]) { for (int k = 0; k < m; ++k) (res.a[i][k] += a[i][j]*1LL*rhs.a[j][k]%MOD) %= MOD; } } } return res; } }tree[N<<2]; inline void push_up(int rt) { tree[rt] = tree[rt<<1]*tree[rt<<1|1]; } void build(int rt, int l, int r) { if(l == r) { tree[rt].reset(l); return ; } int m = l+r >> 1; build(ls); build(rs); push_up(rt); } void update(int p, int rt, int l, int r) { if(l == r) { tree[rt].reset(l); return ; } int m = l+r >> 1; if(p <= m) update(p, ls); else update(p, rs); push_up(rt); } int main(){ fio; cin >> n >> m >> q; for (int i = 1; i <= n; ++i) cin >> b[i]; build(1, 1, n); while(q--) { cin >> op >> x >> y; if(op == 1) { if(b[x][y-1] == \'1\') b[x][y-1] = \'0\'; else b[x][y-1] = \'1\'; update(x, 1, 1, n); } else { cout << tree[1].a[x-1][y-1] << "\n"; } } return 0; }
F
思路:折半枚举,对于每一半的每个状态记录每一行状态为1的行和,最后暴力更新答案。
代码:
#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include<bits/stdc++.h> using namespace std; #define LL long long #define pb push_back const int manx=1e6+10; int n; int a[30][30]; LL mp[(1<<15)][30]; LL mq[(1<<15)][30]; vector<int> vc[18]; int main(){ scanf("%d",&n); for(int i=0;i<2*n;i++){ for(int j=0;j<2*n;j++){ scanf("%d",&a[i][j]); } } int up = 1<<n; for(int i=0;i<up;i++){ for(int j=0;j<n;j++){ if(i&(1<<j)){ for (int k = 0; k < 2*n; ++k) { mp[i][k] += a[k][j]; } } } } for(int i=0;i<up;i++){ for(int j=0;j<n;j++){ if(i&(1<<j)){ for (int k = 0; k < 2*n; ++k) { mq[i][k] += a[k][j+n]; } } } vc[n-__builtin_popcount(i)].pb(i); } LL ans = 0; for (int i = 0; i < up; ++i) { int x = __builtin_popcount(i); for (int j : vc[x]){ LL t = 0; for (int k = 0; k < n; ++k) { if((i&(1<<k)) == 0) t += mp[i][k]+mq[j][k]; if((j&(1<<k)) == 0) t += mp[i][n+k]+mq[j][n+k]; } ans = max(ans, t); } } printf("%lld\n", ans); return 0; }
G
思路:平面直线图模板题。
H
思路:将每个最大面积和次大面积的左上角扔进map里去重。
代码:
#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include<bits/stdc++.h> using namespace std; #define y1 y11 #define fi first #define se second #define pi acos(-1.0) #define LL long long //#define mp make_pair #define pb emplace_back #define ls rt<<1, l, m #define rs rt<<1|1, m+1, r #define ULL unsigned LL #define pll pair<LL, LL> #define pli pair<LL, int> #define pii pair<int, int> #define piii pair<pii, int> #define pdd pair<double, double> #define mem(a, b) memset(a, b, sizeof(a)) #define debug(x) cerr << #x << " = " << x << "\n"; #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); //head const int N = 1e3 + 5; int l[N][N], r[N][N], up[N][N], a[N][N], n, m; char s[N][N]; map<int, vector<pii>, greater<int>> mp; int main() { scanf("%d %d",&n, &m); for (int i = 1; i <= n; ++i) scanf("%s", s[i]+1); for (int i = 1; i <= n; ++i) for (int j = 1; j <= m; ++j) a[i][j] = s[i][j]-\'0\'; for (int i = 1; i <= n; ++i) { for (int j = 1; j <= m; ++j) { if(a[i][j]) l[i][j] = l[i][j-1]+1; } for (int j = m; j >= 1; --j) { if(a[i][j]) r[i][j] = r[i][j+1]+1; } } for (int i = 1; i <= n; ++i) { for (int j = 1; j <= m; ++j) { if(a[i][j]) { up[i][j] = up[i-1][j]+1; if(a[i-1][j]) { l[i][j] = min(l[i-1][j], l[i][j]); r[i][j] = min(r[i-1][j], r[i][j]); } int A = up[i][j], B = r[i][j]+l[i][j]-1; mp[A*B].pb(i-up[i][j]+1, j-l[i][j]+1); mp[A*(B-1)].pb(i-up[i][j]+1, j-l[i][j]+1); mp[(A-1)*B].pb(i-up[i][j]+1, j-l[i][j]+1); } } } int t = 0; for (auto &it : mp) { sort(it.se.begin(), it.se.end()); it.se.erase(unique(it.se.begin(), it.se.end()), it.se.end()); for (int i = 0; i < it.se.size(); ++i) { ++t; if(t == 2) { printf("%d\n", it.fi); return 0; } } } printf("0\n"); return 0; }
I
J
思路:将每个答案的区间包含的点扣出来然后求前缀和,详见队友博客
队友代码:
#include <bits/stdc++.h> 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; template<class T> void _R(T &x) { cin >> x; } void _R(int &x) { scanf("%d", &x); } void _R(ll &x) { scanf("%lld", &x); } void _R(double &x) { scanf("%lf", &x); } void _R(char &x) { scanf(" %c", &x); } void _R(char *x) { scanf("%s", x); } void R() {} template<class T, class... U> void R(T &head, U &... tail) { _R(head); R(tail...); } 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; } const int inf = 0x3f3f3f3f; const ll inff = 0x3f3f3f3f3f3f3f3f; const int mod = 1e9+7; /**********showtime************/ const int maxm = 2e7+9; const int maxn = 1e6+9; int le[maxn],ri[maxn]; int lto[maxn],rto[maxn]; ll f[maxm]; int g(int x) { return x + 10000000; } int main(){ int n; scanf("%d", &n); for(int i=1; i<=n; i++) scanf("%d%d", &le[i], &ri[i]); int sum = 0; /// 向右扩展 le[n+1] = 1000000000; for(int i=1; i<=n; i++) { sum += ri[i] - le[i] + 1; rto[i] = min(sum, le[i+1] - ri[i] - 1); sum -= le[i+1] - ri[i] - 1; if(sum < 0) sum = 0; } /// 向左扩展 sum = 0; ri[0] = -1; for(int i=n; i>=1; i--) { sum += ri[i] - le[i] + 1; lto[i] = min(sum , le[i] - ri[i-1] -1); sum -= le[i] - ri[i-1] - 1; if(sum < 0) sum = 0; } ///计算每个点的前缀和。lowsum保存前缀和比当前点小的个数 ll ans = 0, lowsum = 0; int s = 0, pos = 0; f[g(0)] = 1; for(int i=1; i<=n; i++) { for(int j=max(pos, le[i] - lto[i]); j<=ri[i] + rto[i]; j++) { if(j>=le[i] && j <= ri[i]) { lowsum += f[g(s)]; s++; f[g(s)]++; ans += lowsum; } else { s--; lowsum -= f[g(s)]; f[g(s)]++; ans += lowsum; } // cout<<j<<" "<<lowsum<<endl; pos = j+1; } } // cout<<endl; printf("%lld\n", ans); return 0; }
题号 | 标题 | 团队的状态 |
---|---|---|
A | Graph Games | 通过 |
B | Crazy Binary String | 通过 |
C | Guessing ETT | 未通过 |
D | Big Integer | 通过 |
E | Trees in the Pocket II | 未通过 |
F | Planting Trees | 通过 |
G | Removing Stones | 通过 |
H | Magic Line | 通过 |
I | Median | 通过 |
J | LRU management | 通过 |
A
思路:将点按度数分成两种点,大于$\sqrt{m}$的称为大点,否则称为小点。然后再对边分块,修改边的话,边缘块直接修改,整块直接反转。
然后还需要先预处理出每个块对大点的贡献。对于每个小点暴力查询连接的每条边是否反转;对于每个大点,考虑每个块是否反转,并对它产生多少贡献。
代码:
#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include<bits/stdc++.h> using namespace std; #define y1 y11 #define fi first #define se second #define pi acos(-1.0) #define LL long long //#define mp make_pair #define pb push_back #define ls rt<<1, l, m #define rs rt<<1|1, m+1, r #define ULL unsigned LL #define pll pair<LL, LL> #define pli pair<LL, int> #define pii pair<int, int> #define piii pair<pii, int> #define pdd pair<double, double> #define mem(a, b) memset(a, b, sizeof(a)) #define debug(x) cerr << #x << " = " << x << "\n"; #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); //head struct FastIO { static const int S = 4e6; int wpos; char wbuf[S]; FastIO() : wpos(0) {} inline int xchar() { static char buf[S]; static int len = 0, pos = 0; if (pos == len) pos = 0, len = fread(buf, 1, S, stdin); if (pos == len) exit(0); return buf[pos++]; } inline int xuint() { int c = xchar(), x = 0; while (c <= 32) c = xchar(); for (; \'0\' <= c && c <= \'9\'; c = xchar()) x = x * 10 + c - \'0\'; return x; } inline int xint() { int s = 1, c = xchar(), x = 0; while (c <= 32) c = xchar(); if (c == \'-\') s = -1, c = xchar(); for (; \'0\' <= c && c <= \'9\'; c = xchar()) x = x * 10 + c - \'0\'; return x * s; } inline void xstring(char *s) { int c = xchar(); while (c <= 32) c = xchar(); for (; c > 32; c = xchar()) * s++ = c; *s = 0; } inline void wchar(int x) { if (wpos == S) fwrite(wbuf, 1, S, stdout), wpos = 0; wbuf[wpos++] = x; } inline void wint(int x) { if (x < 0) wchar(\'-\'), x = -x; char s[24]; int n = 0; while (x || !n) s[n++] = \'0\' + x % 10, x /= 10; while (n--) wchar(s[n]); wchar(\'\n\'); } inline void wstring(const char *s) { while (*s) wchar(*s++); } ~FastIO() { if (wpos) fwrite(wbuf, 1, wpos, stdout), wpos = 0; } } io; const int N = 1e5 + 5; vector<int> g[N]; int T, n, m, d[N], u[N*2], v[N*2], op, l, r, q, id[N*2]; LL val[N], res[N], f[N][500]; bool ty[N]; struct BLOCK { int bl[N*2], block, blo[1000]; inline void init() { for (int i = 1; i <= m; ++i) bl[i] = (i-1)/block + 1; for (int i = 1; i <= bl[m]; ++i) blo[i] = 0; } inline void update(int L, int R) { if(bl[L] == bl[R]) { for (int i = L; i <= R; ++i) res[u[i]] ^= val[v[i]], res[v[i]] ^= val[u[i]]; return ; } for (int i = L; i <= bl[L]*block; ++i) res[u[i]] ^= val[v[i]], res[v[i]] ^= val[u[i]]; for (int i = bl[L]+1; i <= bl[R]-1; ++i) blo[i] ^= 1; for (int i = (bl[R]-1)*block+1; i <= R; ++i) res[u[i]] ^= val[v[i]], res[v[i]] ^= val[u[i]]; } }b; int main() { mt19937 mt_rand(time(NULL)); T = io.xint(); while(T--) { n = io.xint(); m = io.xint(); for (int i = 1; i <= n; ++i) val[i] = mt_rand()%LONG_MAX; for (int i = 1; i <= m; ++i) u[i] = io.xint(), v[i] = io.xint(), g[u[i]].pb(i), g[v[i]].pb(i), d[u[i]]++, d[v[i]]++; int blo = sqrt(m)+1; b.block = blo; b.init(); for (int i = 1; i <= n; ++i) { if(d[i] <= blo) ty[i] = 0; else ty[i] = 1; } for (int i = 1; i <= n; ++i) if(ty[i]) for (int j = 1; j <= b.bl[m]; ++j) f[i][j] = 0; for (int i = 1; i <= n; ++i) { for (int id : g[i]) { int y = u[id]^v[id]^i; res[i] ^= val[y]; if(ty[i]) f[i][b.bl[id]] ^= val[y]; } } q = io.xint(); for (int i = 1; i <= q; ++i) { op = io.xint(); l = io.xint(); r = io.xint(); if(op == 1) { b.update(l, r); } else { LL v1 = res[l], v2 = res[r]; if(ty[l]) {for (int j = 1; j <= b.bl[m]; ++j) if(b.blo[j]) v1 ^= f[l][j];} else for (int id : g[l]) if(b.blo[b.bl[id]]) v1 ^= val[u[id]^v[id]^l]; if(ty[r]) {for (int j = 1; j <= b.bl[m]; ++j) if(b.blo[j]) v2 ^= f[r][j];} else for (int id : g[r]) if(b.blo[b.bl[id]]) v2 ^= val[u[id]^v[id]^r]; putchar((v1==v2)+\'0\'); } } putchar(\'\n\'); for(int i = 1; i <= n; ++i) d[i] = 0, g[i].clear(), res[i] = 0; for (int i = 1; i <= m; ++i) id[i] = 0; } return 0; }
B
思路:对于最长子段的计算,只要把0看成-1,对于每个前缀和记录最前面出现的位置
代码:
#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include<bits/stdc++.h> using namespace std; #define fi first #define se second #define pi acos(-1.0) #define LL long long //#define mp make_pair #define pb push_back #define ls rt<<1, l, m #define rs rt<<1|1, m+1, r #define ULL unsigned LL #define pll pair<LL, LL> #define pii pair<int, int> #define piii pair<pii, int> #define mem(a, b) memset(a, b, sizeof(a)) #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); #define fopen freopen("in.txt", "r", stdin);freopen("out.txt", "w", stout); //head const int N = 1e5 + 10; char s[N]; int n, sum[N], a, b, c1, c0; map<int, int> mp; int main() { scanf("%d", &n); scanf("%s", s+1); for (int i = 1; i <= n; ++i) if(s[i] == \'1\') c1++; else c0++; b = min(c1, c0)*2; mp[0] = 0; for (int i = 1; i <= n; ++i) { if(s[i] == \'1\') sum[i] = sum[i-1]+1; else sum[i] = sum[i-1]-1; if(mp.find(sum[i]) != mp.end()) a = max(a, i-mp[sum[i]]); else mp[sum[i]] = i; } printf("%d %d\n", a, b); return 0; }
C
D
思路:首先有一个公式$\frac{x}{d}\%k = \frac{x\%k*d}{d}$。那么原式$\frac{10^x-1}{9}\%p$可以化简$10^x = 1(\%(9*p))$。或者模数不乘$9$,但$p=3$时要特判。
当$p = 2, 5$时,答案肯定是$0$。否则,求出最小的x满足等式,这个可以用费马小定理或者BSGS。然后就是求多少对$(i, j)$使得$x | i^j$。我们先把$x$分解
质因数$x={p_1}^{a_1} {p_2}^{a_2}...{p_n}^{a_n}$,然后枚举$j$,那么对于一个固定的$j$,我们发现$y = p_{1}^{\lceil\frac{a_{1}}{j}\rceil}p_{2}^{\lceil\frac{a_{2}}{j}\rceil}...p_{n}^{\lceil\frac{a_{n}}{j}\rceil} $的倍数的$j$次方一定是$x$的倍数, 那么就是求小于$n$的数中有多少个是$y$的倍数。当$j \ge 30$时,$y$的质因子的幂次都变成了$1$。
代码:
#include<bits/stdc++.h> #define ll long long #define LL long long using namespace std; LL qpow(LL n, LL k) { LL ans = 1; if(k == -1) return 0; while(k) { if(k&1) ans = (ans*n); n = (n*n); k >>= 1; } return ans; } unordered_map<int, int> mp; LL q_pow(LL n, LL k, LL p) { LL ans = 1; if(k == -1) return 0; while(k) { if(k&1) ans = (ans*n) % p; n = (n*n) % p; k >>= 1; } return ans; } int BSGS(int a, int b, int p){ int m = sqrt(p)+1, s = b; mp.clear(); for(int i = 0; i < m; ++i){ mp[s]=i; s= (s*1LL*a)%p; } int t = q_pow(a, m, p); s = 1; for(int i = 1; i <= m; ++i){ s = (s*1LL*t)%p; if(mp.find(s) != mp.end()) return i*m-mp[s]; } return -1; } int p,n,m; vector<pair<int,int> > vs; void make(int p){ vs.clear(); for(int i=2;i*i<=p;i++){ if(p%i==0){ int c=0; while(p%i==0){ c++; p/=i; } vs.push_back({i,c}); } } if(p!=1) vs.push_back({p,1}); ll num=0; ll temp=1; for(int j=1;j<=min(30,m);j++){ temp=1; for(int i=0; i<vs.size(); i++){ temp=temp*qpow(vs[i].first,ceil(1.0*vs[i].second/j)); } num+=n/temp; } if (m>30) num+=1ll*(m-30)*(n/temp); printf("%lld\n",num); } int main(){ int T; scanf("%d",&T); while(T--){ scanf("%d %d %d",&p,&n,&m); if(p==2 || p==5) { printf("0\n"); continue; } int x=BSGS(10,1,p);// cout<<x<<endl; if(p==3) x=3; make(x); } }
E
F
思路:用枚举上边界l和下边界r,先对于每一列求出最大值最小值,然后用单调队列维护。这道题很卡常,有个用两次单调队列的$n^3$写法被卡掉了。
代码:
#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include<bits/stdc++.h> using namespace std; #define fi first #define se second #define pi acos(-1.0) #define LL long long //#define mp make_pair #define pb push_back #define ls rt<<1, l, m #define rs rt<<1|1, m+1, r #define ULL unsigned LL #define pll pair<LL, LL> #define pii pair<int, int> #define piii pair<pii, int> #define mem(a, b) memset(a, b, sizeof(a)) #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); #define fopen freopen("in.txt", "r", stdin);freopen("out.txt", "w", stout); //head const int N = 505; const int INF = 0x3f3f3f3f; int a[N][N], mn[N], mx[N]; int q1[N*2], q2[N*2], T, n, m; int main() { scanf("%d", &T); while(T--){ scanf("%d %d", &n, &m); for (int i = 1; i <= n; ++i) for (int j = 1; j <= n; ++j) scanf("%d", &a[i][j]); int ans = 0; for (int i = 1; i <= n; ++i) { for (int j = 1; j <= n; ++j) mn[j] = INF, mx[j] = -INF; for (int j = i; j <= n; ++j) { for (int k = 1; k <= n; ++k) mn[k] = min(a[j][k], mn[k]), mx[k] = max(a[j][k], mx[k]); int le1 = N, ri1 = N-1; int le2 = N, ri2 = N-1; int pre = 0; for (int k = 1; k <= n; ++k) { while(le1 <= ri1 && mn[q1[ri1]] >= mn[k]) ri1--; q1[++ri1] = k; while(le2 <= ri2 && mx[q2[ri2]] <= mx[k]) ri2--; q2[++ri2] = k; while(pre < k && mx[q2[le2]]-mn[q1[le1]] > m) { ++pre; while(le1 <= ri1 && q1[le1] <= pre) le1++; while(le2 <= ri2 && q2[le2] <= pre) le2++; } if(pre < k && mx[q2[le2]] - mn[q1[le1]] <=m) ans = max(ans, (k - pre)*(j-i+1)); } } } printf("%d\n", ans); } return 0; }
G
思路:分治,对于每个分治的区间$[L,R]$,求出最大值的位置$p$,然后枚举$[L,p]$或者$[p,R]$中小的区间中的每个位置,然后找另一个端点的位置。
然后递归区间$[L,p-1]$和区间$[p+1,R]$。时间复杂度$O(n*log(n))$
代码:
#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include<bits/stdc++.h> using namespace std; #define y1 y11 #define fi first #define se second #define pi acos(-1.0) #define LL long long //#define mp make_pair #define pb emplace_back #define ls rt<<1, l, m #define rs rt<<1|1, m+1, r #define ULL unsigned LL #define pll pair<LL, LL> #define pli pair<LL, int> #define pii pair<int, int> #define piii pair<pii, int> #define pdd pair<double, double> #define mem(a, b) memset(a, b, sizeof(a)) #define debug(x) cerr << #x << " = " << x << "\n"; #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); //head const int N = 3e5 + 5; int T, n, a[N], st[N][20], lg[N]; LL sum[N]; LL ans = 0; inline void init() { for (int i = n; i >= 1; --i) { st[i][0] = i; for (int j = 1; i+(1<<j-1)-1 <= n; ++j) { if(a[st[i][j-1]] > a[st[i+(1<<j-1)][j-1]]) st[i][j] = st[i][j-1]; else st[i][j] = st[i+(1<<j-1)][j-1]; } } } inline int get_max(int L, int R) { int k = lg[R-L+1], x = st[L][k], y = st[R-(1<<k)+1][k]; if(a[x] > a[y]) return x; else return y; } void solve(int L, int R) { if(L >= R) return ; int p = get_max(L, R); if(p-L < R-p) { int j = p; for (int i = L; i <= p; ++i) { while(j <= R && sum[j]-sum[i-1] < 2*a[p]) ++j; ans += R-j+1; } } else { int j = p; for (int i = R; i >= p; --i) { while(j >= L && sum[i]-sum[j==0?j:j-1] < 2*a[p]) --j; ans += j-L+1; } } solve(L, p-1); solve(p+1, R); } int main() { for (int i = 2; i < N; ++i) lg[i]=lg[i>>1]+1; scanf("%d", &T); while(T--) { scanf("%d", &n); for (int i = 1; i <= n; ++i) scanf("%d", &a[i]), sum[i] = sum[i-1]+a[i]; init(); ans = 0; solve(1, n); printf("%lld\n", ans); } return 0; }
H
思路:构造
代码:
#include<bits/stdc++.h> using namespace std; #define ll long long const int maxn=2e3+10; vector<int> vs[maxn]; int32_t main(){ int T; scanf("%d",&T); while(T--){ int n; scanf("%d",&n); for(int i=1;i<=n;i++){ int x,y; scanf("%d %d",&x,&y); x+=1000; y+=1000; vs[x].push_back(y); } int temp=0; for(int i=0;i<=2000;i++){ if(temp+vs[i].size()>=n/2){ int d=n/2-temp; sort(vs[i].begin(),vs[i].end()); int y=vs[i][d-1]; if(y>=1000){ int x1=i+1; x1-=1000; int y1=-1; y1-=1000; int x2=i+3; x2-=1000; int y2=-2*y-4; y2-=1000; printf("%d %d %d %d\n",x1,y1,x2,y2); } else { int x1=i-1; int y1=2001; int x2=i-3; int y2=-2*y+6003-1; printf("%d %d %d %d\n",x1-1000,y1-1000,x2-1000,y2-1000); } break; } temp+=vs[i].size(); } for(int i=0;i<=2000;i++) vs[i].clear(); } }
I
思路:如果可以构造,那么$a_i$一定可以选择$b_i,b_{i-1},b_{i-2}$中的一个值,具体证明看题解。那么可以想到一个状态$dp[i][j][k]$,其中,$j$和$k$
分别表示$i$和$i-1$这两个位置选择的$b_i$和本身之间的距离,那判断一下相邻两个之间的转移可不可行就可以转移了。
代码:
#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include<bits/stdc++.h> using namespace std; #define y1 y11 #define fi first #define se second #define pi acos(-1.0) #define LL long long //#define mp make_pair #define pb push_back #define ls rt<<1, l, m #define rs rt<<1|1, m+1, r #define ULL unsigned LL #define pll pair<LL, LL> #define pli pair<LL, int> #define pii pair<int, int> #define piii pair<pii, int> #define pdd pair<double, double> #define mem(a, b) memset(a, b, sizeof(a)) #define debug(x) cerr << #x << " = " << x << "\n"; #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); //head const int N = 1e5 + 5; bool dp[N][3][3]; int pre[N][3][3]; int T, n, b[N], a[N]; inline int ck(int x, int y, int z) { if(b[x] >= b[y] && b[x] >= b[z]) return max(b[y], b[z]); if(b[y] >= b[x] && b[y] >= b[z]) return max(b[x], b[z]); return max(b[x], b[y]); } int main() { scanf("%d", &T); while(T--) { scanf("%d", &n); for (int i = 1; i <= n-2; ++i) scanf("%d", &b[i]); if(n == 3) { for (int i = 1; i <= 3; ++i) printf("%d ", b[1]); printf("\n"); continue; } for (int i = 1; i <= n; ++i) for (int j = 0; j < 3; ++j) for (int k = 0; k < 3; ++k) dp[i][j][k] = 0; for (int i = 1; i <= n; ++i) { if(i == 1) ; else if(i == 2) { for (int j = 0; j < 3; ++j) { if(2-j < 1) break; for (int k = 0; k < 3; ++k) { if(1-k < 1) break; dp[i][j][k] = 1; } } } else { for (int j = 0; j < 3; ++j) { for (int k = 0; k < 3; ++k) { if(dp[i-1][j][k]) { for (int l = 0; l < 3; ++l) { if(i-l <= n-2) { if(ck(i-2-k, i-1-j, i-l) == b[i-2]) dp[i][l][j] = 1, pre[i][l][j] = k; } } } } } } } int x, y, z; bool f = false; for (int j = 0; j < 3; ++j) for (int k = 0; k < 3; ++k) if(dp[n][j][k]) { f = true; x = n; y = j; z = k; break; } if(f) { while(x) { a[x] = b[x-y]; int tmp = z; z = pre[x][y][z]; y = tmp; x--; } for (int i = 1; i <= n; ++i) printf("%d%c", a[i], " \n"[i==n]); } else printf("-1\n"); } return 0; }
J
思路:用平衡树维护,其实用set就可以了,记录一下每个串最后的位置,如果这个串被删除,也要记得删除位置
代码:
#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include<bits/stdc++.h> using namespace std; #define fi first #define se second #define pi acos(-1.0) #define LL long long //#define mp make_pair #define pb push_back #define ls rt<<1, l, m #define rs rt<<1|1, m+1, r #define ULL unsigned LL #define pll pair<LL, LL> #define pii pair<int, int> #define piii pair<pii, int> #define mem(a, b) memset(a, b, sizeof(a)) #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); #define fopen freopen("in.txt", "r", stdin);freopen("out.txt", "w", stout); //head const int N = 5e5 + 10; int ch[N][2], val[N], cnt[N], V[N], fa[N], sz[N], ncnt = 0, rt = 0; string tmp[N]; inline int ck(int x) { return ch[fa[x]][1] == x; } inline void push_up(int x) { sz[x] = sz[ch[x][0]] + sz[ch[x][1]] + cnt[x]; } void Rotate(int x) { int y = fa[x], z = fa[y]; int k = ck(x), w = ch[x][k^1]; ch[y][k] = w, fa[w] = y; ch[z][ck(y)] = x, fa[x] = z; ch[x][k^1] = y, fa[y] = x; push_up(y), push_up(x); } void Splay(int x, int goal = 0) { while(fa[x] != goal) { int y = fa[x], z = fa[y]; if(z != goal) { if(ck(x) == ck(y)) Rotate(y); else Rotate(x); } Rotate(x); } if(!goal) rt = x; } void Find(int x) { if(!rt) return ; int cur = rt; while(ch[cur][x>val[cur]] && x != val[cur]) cur = ch[cur][x>val[cur]]; Splay(cur); } void Insert(int x, int y, string s) { int cur = rt, p = 0; while(cur && val[cur] != x) { p = cur; cur = ch[cur][x>val[cur]]; } if(cur) cnt[cur]++; else { cur = ++ncnt; if(p) ch[p][x>val[p]] = cur; fa[cur] = p; ch[cur][0] = ch[cur][1] = 0; val[cur] = x; V[cur] = y; tmp[cur] = s; cnt[cur] = sz[cur] = 1; } Splay(cur); } int Kth(int k) { int cur = rt; while(true) { if(ch[cur][0] && k <= sz[ch[cur][0]]) cur = ch[cur][0]; else if(k > sz[ch[cur][0]] + cnt[cur]) k -=sz[ch[cur][0]] + cnt[cur], cur = ch[cur][1]; else return cur; } } inline int get_min(int x) { while(x && ch[x][0]) x = ch[x][0]; return x; } inline int get_max(int x) { while(x && ch[x][1]) x = ch[x][1]; return x; } int Pre(int x) { Find(x); if(val[rt] < x) return rt; if(!ch[rt][0]) return -1; int cur = ch[rt][0]; while(ch[cur][1]) cur = ch[cur][1]; return cur; } int Succ(int x) { Find(x); if(val[rt] > x) return rt; if(!ch[rt][1]) return -1; int cur = ch[rt][1]; while(ch[cur][0]) cur = ch[cur][0]; return cur; } void Remove(int x) { int last = Pre(x), next = Succ(x); Splay(last), Splay(next, last); int del = ch[next][0]; if(cnt[del] > 1) cnt[del]--, Splay(del); else ch[next][0] = 0, push_up(next), push_up(last); } void delete_root() { if(ch[rt][1]) { int cur = ch[rt][1]; while(cur && ch[cur][0]) cur = ch[cur][0]; Splay(cur, rt); ch[cur][0] = ch[rt][0]; fa[ch[cur][0]] = cur; rt = cur; } else rt = ch[rt][0]; fa[rt] = 0; if(rt) push_up(rt); } inline void init() { ncnt = rt = ch[0][0] = ch[0][1] = fa[0] = sz[0] = cnt[0] = val[0] = 0; // V[0] = -10; } int q, m, op, v, T; string s; unordered_map<string, int> mp; int main() { fio; cin >> T; while(T--) { init(); mp.clear(); Insert(-1, -10, "0"); Insert(N-1, -10, "0"); cin >> q >> m; int now = 0; for (int i = 1; i <= q; ++i){ cin >> op >> s >> v; int res = 0; if(op == 0) { if(mp.find(s) == mp.end()) { mp[s] = ++now; Insert(now, v, s); res = v; } else { Find(mp[s]); res = V[rt]; Remove(mp[s]); mp[s] = ++now; Insert(now, res, s); } cout << res << "\n"; } else { if(mp.find(s) == mp.end()) { cout << "Invalid\n"; } else { if(v == 0) { Find(mp[s]); cout << V[rt] << "\n"; } else if(v == -1) { int cur = Pre(mp[s]); if(V[cur] == -10) cout << "Invalid\n"; else cout << V[cur] << "\n"; } else { int cur = Succ(mp[s]); if(V[cur] == -10) cout << "Invalid\n"; else cout << V[cur] << "\n"; } } } if(sz[rt]-2 > m) { int cur = Kth(2); Splay(cur); delete_root(); mp.erase(tmp[cur]); } } } return 0; }
题号 | 标题 | 团队的状态 |
---|---|---|
A | meeting | 通过 |
B | xor | 通过 |
C | sequence | 通过 |
D | triples I | 通过 |
E | triples II | 通过 |
F | merge | 通过 |
G | tree | 未通过 |
H | RNGs | 未通过 |
I | string | 通过 |
J | free | 通过 |
K | number | 通过 |
A
思路:虚树直径的一半。
代码:
#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include<bits/stdc++.h> using namespace std; #define y1 y11 #define fi first #define se second #define pi acos(-1.0) #define LL long long //#define mp make_pair #define pb emplace_back #define ls rt<<1, l, m #define rs rt<<1|1, m+1, r #define ULL unsigned LL #define pll pair<LL, LL> #define pli pair<LL, int> #define pii pair<int, int> #define piii pair<pii, int> #define pdd pair<double, double> #define mem(a, b) memset(a, b, sizeof(a)) #define debug(x) cerr << #x << " = " << x << "\n"; #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); //head const int N = 1e5 + 5; vector<int> g[N]; int a[N], sz[N], sum[N], n, k, u, v, s, mx; void dfs(int u, int o, int d) { if(a[u]) { if(d > mx) { mx = d; s = u; } } for (int v : g[u]) { if(v != o){ dfs(v, u, d+1); } } } int main() { scanf("%d %d", &n, &k); for (int i = 1; i < n; ++i) { scanf("%d %d", &u, &v); g[u].pb(v); g[v].pb(u); } for (int i = 1; i <= k; ++i) scanf("%d", &u), ++a[u]; dfs(u, u, 0); dfs(s, s, 0); if(mx%2) printf("%d\n", (mx+1)/2); else printf("%d\n", mx/2); return 0; }
B
思路:线性基求交+线段树。建树的复杂度是$O(n*32*32)$,查询时不需要把需要查询区间的交算出来,不然单次查询复杂度$O(32*32*log(n))$,
只需要判断这段区间在线段树上的每个节点是不是可以表示$x$就可以了,这样单次查询复杂度$O(32*log(n))$。
代码:
#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include<bits/stdc++.h> using namespace std; #define y1 y11 #define fi first #define se second #define pi acos(-1.0) #define LL long long //#define mp make_pair #define pb emplace_back #define ls rt<<1, l, m #define rs rt<<1|1, m+1, r #define ULL unsigned LL #define pll pair<LL, LL> #define pli pair<LL, int> #define pii pair<int, int> #define piii pair<pii, int> #define pdd pair<double, double> #define mem(a, b) memset(a, b, sizeof(a)) #define debug(x) cerr << #x << " = " << x << "\n"; #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); //head const int N = 5e4 + 5; struct LinearBase { LL v[32]; inline void clr() {memset(v, 0, sizeof(v));} inline void ins(LL a) { for (int i = 31; i >= 0; --i) { if(a&(1LL<<i)) { if(!v[i]) { v[i] = a; break; } a ^= v[i]; } } } inline bool can_ex(LL a) { for (int i = 31; i >= 0; --i) if((a^v[i]) < a) a ^= v[i]; return a == 0; } //交 inline friend LinearBase operator * (const LinearBase &a, const LinearBase &b) { LinearBase all, c, d; all.clr(), c.clr(), d.clr(); for (int i = 31; i >= 0; --i) { all.v[i] = a.v[i]; d.v[i] = 1LL<<i; } for (int i = 31; i >= 0; --i) { if(b.v[i]) { LL v = b.v[i], k = 0; bool can = true; for (int j = 31; j >= 0; --j) { if(v&(1LL<<j)) { if(all.v[j]) { v ^= all.v[j]; k ^= d.v[j]; } else { can = false; all.v[j] = v; d.v[j] = k; break; } } } if(can) { LL v = 0; for (int j = 31; j >= 0; --j) { if(k&(1LL<<j)) { v ^= a.v[j]; } } c.ins(v); } } } return c; } }tree[N<<2]; vector<LL> vc[N]; inline void push_up(int rt) { tree[rt] = tree[rt<<1]*tree[rt<<1|1]; } void build(int rt, int l, int r) { if(l == r) { tree[rt].clr(); for (LL x : vc[l]) tree[rt].ins(x); return ; } int m = l+r >> 1; build(ls); build(rs); push_up(rt); } bool query(int L, int R, LL a, int rt, int l, int r) { if(L <= l && r <= R) return tree[rt].can_ex(a); int m = l+r >> 1; if(L <= m && m < R) return query(L, R, a, ls)&query(L, R, a, rs); if(L <= m) return query(L, R, a, ls); else return query(L, R, a, rs); } int n, m, t, l, r; LL a; int main() { scanf("%d %d", &n, &m); for (int i = 1; i <= n; ++i) { scanf("%d", &t); vc[i].resize(t); for (int j = 0; j < t; ++j) scanf("%lld", &vc[i][j]); } build(1, 1, n); while(m--) { scanf("%d %d %lld", &l, &r, &a); if(query(l, r, a, 1, 1, n)) printf("YES\n"); else printf("NO\n"); } return 0; }
C
思路:南昌邀请赛原题。
先对b数组求个前缀和,然后用单调栈求出以每个位置$p$为最小值左端点的最左边$L$和右端点的最右边$R$。
如果$a[p] > 0$,用$max\left(sum[i], i\in[p, R]\right)- min\left(sum[i], i\in[L-1, p-1]\right)$;
如果$a[p] < 0$,用$min\left(sum[i], i\in[p, R]\right)- max\left(sum[i], i\in[L-1, p-1]\right)$。
方法一(单调栈+线段树$O(nlog(n))2500ms$)
代码:
#include <bits/stdc++.h> using namespace std; #define LL long long #define fi first #define se second #define pb push_back #define ls rt<<1, l, m #define rs rt<<1|1, m+1, r const int N = 3e6 + 5; int a[N], b[N], pre[N], suf[N]; LL sum[N], mx[N<<2], mn[N<<2]; stack<int> st; int n; void push_up(int rt) { mn[rt] = min(mn[rt<<1], mn[rt<<1|1]); mx[rt] = max(mx[rt<<1], mx[rt<<1|1]); } void build(int rt, int l, int r) { if(l == r) { mx[rt] = mn[rt] = sum[l]; return ; } int m = l+r >> 1; build(ls); build(rs); push_up(rt); } LL querymx(int L, int R, int rt, int l, int r) { if(L <= l && r <= R) return mx[rt]; int m = l+r >> 1; LL ans = LONG_MIN; if(L <= m) ans = max(ans, querymx(L, R, ls)); if(R > m) ans = max(ans, querymx(L, R, rs)); return ans; } LL querymn(int L, int R, int rt, int l, int r) { if(L <= l && r <= R) return mn[rt]; int m = l+r >> 1; LL ans = LONG_MAX; if(L <= m) ans = min(ans, querymn(L, R, ls)); if(R > m) ans = min(ans, querymn(L, R, rs)); return ans; } int main() { scanf("%d", &n); for (int i = 1; i <= n; ++i) scanf("%d", &a[i]); for (int i = 1; i <= n; ++i) scanf("%d", &b[i]); for (int i = 1; i <= n; ++i) sum[i] = sum[i-1] + b[i]; build(1, 0, n); a[0] = a[n+1] = INT_MIN; st.push(0); for (int i = 1; i <= n; ++i) { while(!st.empty() && a[st.top()] >= a[i]) st.pop(); pre[i] = st.top(); st.push(i); } while(!st.empty()) st.pop(); st.push(n+1); for (int i = n; i >= 1; --i) { while(!st.empty() && a[st.top()] >= a[i]) st.pop(); suf[i] = st.top(); st.push(i); } LL ans = -(1LL<<61); for (int i = 1; i <= n; ++i) { int l = pre[i], r = i-1; int ll = i, rr = suf[i]-1; if(a[i] < 0) { ans = max(ans, a[i]*(querymn(ll, rr, 1, 0, n)-querymx(l, r, 1, 0, n))); } else if(a[i] > 0) { ans = max(ans, a[i]*(querymx(ll, rr, 1, 0, n)-querymn(l, r, 1, 0, n))); } } printf("%lld\n", ans); return 0; }
方法二(笛卡尔树+快读$O(n)350ms$,这个快读优化了1200ms,出题人为了卡$log$连读入都卡掉了)
代码:
#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include<bits/stdc++.h> using namespace std; #define y1 y11 #define fi first #define se second #define pi acos(-1.0) #define LL long long //#define mp make_pair #define pb emplace_back #define ls rt<<1, l, m #define rs rt<<1|1, m+1, r #define ULL unsigned LL #define pll pair<LL, LL> #define pli pair<LL, int> #define pii pair<int, int> #define piii pair<pii, int> #define pdd pair<double, double> #define mem(a, b) memset(a, b, sizeof(a)) #define debug(x) cerr << #x << " = " << x << "\n"; #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); //head struct FastIO { static const int S = 4e6; int wpos; char wbuf[S]; FastIO() : wpos(0) {} inline int xchar() { static char buf[S]; static int len = 0, pos = 0; if (pos == len) pos = 0, len = fread(buf, 1, S, stdin); if (pos == len) exit(0); return buf[pos++]; } inline int xuint() { int c = xchar(), x = 0; while (c <= 32) c = xchar(); for (; \'0\' <= c && c <= \'9\'; c = xchar()) x = x * 10 + c - \'0\'; return x; } inline int xint() { int s = 1, c = xchar(), x = 0; while (c <= 32) c = xchar(); if (c == \'-\') s = -1, c = xchar(); for (; \'0\' <= c && c <= \'9\'; c = xchar()) x = x * 10 + c - \'0\'; return x * s; } inline void xstring(char *s) { int c = xchar(); while (c <= 32) c = xchar(); for (; c > 32; c = xchar()) * s++ = c; *s = 0; } inline void wchar(int x) { if (wpos == S) fwrite(wbuf, 1, S, stdout), wpos = 0; wbuf[wpos++] = x; } inline void wint(int x) { if (x < 0) wchar(\'-\'), x = -x; char s[24]; int n = 0; while (x || !n) s[n++] = \'0\' + x % 10, x /= 10; while (n--) wchar(s[n]); wchar(\'\n\'); } inline void wstring(const char *s) { while (*s) wchar(*s++); } ~FastIO() { if (wpos) fwrite(wbuf, 1, wpos, stdout), wpos = 0; } } io; const int N = 3e6 + 10; struct Node { int id, key, par, ch[2]; LL mxlf, mxri, mnlf, mnri; inline bool operator < (Node & rhs) {return id < rhs.id;} inline void init(int _id, int _key, int _par) { key = _key, id = _id, par = _par, ch[0] = ch[1] = 0; } }tree[N]; inline int cartesian_build(int n) { for (int i = 1; i <= n; ++i) { int k = i-1; while(tree[k].key > tree[i].key) k = tree[k].par; tree[i].ch[0] = tree[k].ch[1]; tree[tree[i].ch[0]].par = i; tree[k].ch[1] = i; tree[i].par = k; } return tree[0].ch[1]; } LL ans = LONG_MIN, sum[N]; int n, a[N], b[N], rt; inline void dfs(int u) { tree[u].mxlf = tree[u].mnlf = sum[u-1]; tree[u].mxri = tree[u].mnri = sum[u]; if(tree[u].ch[0]) dfs(tree[u].ch[0]), tree[u].mxlf = max(tree[u].mxlf, tree[tree[u].ch[0]].mxlf), tree[u].mnlf = min(tree[u].mnlf, tree[tree[u].ch[0]].mnlf); if(tree[u].ch[1]) dfs(tree[u].ch[1]), tree[u].mxri = max(tree[u].mxri, tree[tree[u].ch[1]].mxri), tree[u].mnri = min(tree[u].mnri, tree[tree[u].ch[1]].mnri); if(tree[u].key > 0) ans = max(ans, tree[u].key*(tree[u].mxri-tree[u].mnlf)); else ans = max(ans, tree[u].key*(tree[u].mnri-tree[u].mxlf)); if(tree[u].ch[0]) tree[u].mxri = max(tree[u].mxri, tree[tree[u].ch[0]].mxri), tree[u].mnri = min(tree[u].mnri, tree[tree[u].ch[0]].mnri); if(tree[u].ch[1]) tree[u].mxlf = max(tree[u].mxlf, tree[tree[u].ch[1]].mxlf), tree[u].mnlf = min(tree[u].mnlf, tree[tree[u].ch[1]].mnlf); } int main() { n = io.xint(); for (int i = 1; i <= n; ++i) a[i] = io.xint(); tree[0].init(0, -1000001, 0); for (int i = 1; i <= n; ++i) b[i] = io.xint(), sum[i] = sum[i-1]+b[i], tree[i].init(i, a[i], 0); rt = cartesian_build(n); dfs(rt); printf("%lld\n", ans); return 0; }
D
思路:$2^p\%3$:如果$p$是偶数,是1;如果$p$奇数,是2。
然后如果$a\%3==0$,答案就是本身;如果$a\% 3==1$,可以取出一个偶数位或两个奇数位,然后考虑怎把这些位和之前的位构成3的倍数;如果$a\%3==2$,同理。
代码:
#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include<bits/stdc++.h> using namespace std; #define y1 y11 #define fi first #define se second #define pi acos(-1.0) #define LL long long //#define mp make_pair #define pb emplace_back #define ls rt<<1, l, m #define rs rt<<1|1, m+1, r #define ULL unsigned LL #define pll pair<LL, LL> #define pli pair<LL, int> #define pii pair<int, int> #define piii pair<pii, int> #define pdd pair<double, double> #define mem(a, b) memset(a, b, sizeof(a)) #define debug(x) cerr << #x << " = " << x << "\n"; #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); //head int T; LL a; vector<int> vc[2]; vector<LL> res; int main() { scanf("%d", &T); while(T--) { vc[0].clear(); vc[1].clear(); res.clear(); scanf("%lld", &a); for (int i = 0; i <= 61; ++i) { if(a&(1LL<<i)) vc[i%2].pb(i); } if(a%3 == 0) { res.pb(a); } else if(a%3 == 2) { bool f = false; if(vc[1].size() > 0) { if(vc[0].size() > 0) { int x = vc[1][0], y = vc[0][0]; res.pb(a^(1LL<<x)); res.pb((1LL<<x)|(1LL<<y)); f = true; } if(vc[1].size() >= 3) { int x = vc[1][0], y = vc[1][1], z = vc[1][2]; res.pb(a^(1LL<<x)); res.pb((1LL<<x)^(1LL<<y)^(1LL<<z)); f = true; } } if(!f && vc[0].size() >= 3) { int x = vc[0][0], y = vc[0][1], z = vc[0][2]; res.pb(a^(1LL<<x)^(1LL<<y)); res.pb((1LL<<x)^(1LL<<y)^(1LL<<z)); f = true; } } else { bool f = false; if(vc[0].size() > 0) { if(vc[1].size() > 0) { int x = vc[0][0], y = vc[1][0]; res.pb(a^(1LL<<x)); res.pb((1LL<<x)|(1LL<<y)); f = true; } if(vc[0].size() >= 3) { int x = vc[0][0], y = vc[0][1], z = vc[0][2]; res.pb(a^(1LL<<x)); res.pb((1LL<<x)^(1LL<<y)^(1LL<<z)); f = true; } } if(!f && vc[1].size() >= 3) { int x = vc[1][0], y = vc[1][1], z = vc[1][2]; res.pb(a^(1LL<<x)^(1LL<<y)); res.pb((1LL<<x)^(1LL<<y)^(1LL<<z)); f = true; } } printf("%d ", (int)res.size()); //LL t = 0; for (int i = 0; i <res.size(); ++i) printf("%lld%c", res[i], " \n"[i+1==res.size()]); //cout << t << endl; } return 0; }
E
思路:二维二项式反演。
代码:
#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include<bits/stdc++.h> using namespace std; #define y1 y11 #define fi first #define se second #define pi acos(-1.0) #define LL long long //#define mp make_pair #define pb push_back #define ls rt<<1, l, m #define rs rt<<1|1, m+1, r #define ULL unsigned LL #define pll pair<LL, LL> #define pli pair<LL, int> #define pii pair<int, int> #define piii pair<pii, int> #define pdd pair<double, double> #define mem(a, b) memset(a, b, sizeof(a)) #define debug(x) cerr << #x << " = " << x << "\n"; #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); //head const int MOD = 998244353; int T, c1, c2; LL n, a, C[65][65], f[65][65]; inline LL q_pow(LL n, LL k) { LL res = 1; while(k) { if(k&1) res = (res*n)%MOD; n = (n*n)%MOD; k >>= 1; } return res; } inline void init() { C[0][0] = 1; for (int i = 1; i < 65; ++i) { C[i][0] = 1; for (int j = 1; j <= i; ++j) C[i][j] = (C[i-1][j]+C[i-1][j-1])%MOD; } for (int i = 0; i < 65; ++i) { for (int j = 0; j < 65; ++j) { for (int ii = 0; ii <= i; ++ii) { for (int jj = 0; jj <= j; ++jj) { if((ii*1+jj*2)%3 == 0) { (f[i][j] += C[i][ii]*C[j][jj]%MOD) %= MOD; } } } } } } int main() { init(); scanf("%d", &T); while(T--) { scanf("%lld %lld", &n, &a); c1 = c2 = 0; for (int i = 0; i <= 60; ++i) { if(a&(1LL<<i)) { if(i%2 == 0) ++c1; else ++c2; } } LL ans = 0; for (int i = 0; i <= c1; ++i) { for (int j = 0; j <= c2; ++j) { if((c1-i+c2-j)%2 == 0) (ans += C[c1][i]*C[c2][j]%MOD*q_pow(f[i][j], n)) %= MOD; else (ans -= C[c1][i]*C[c2][j]%MOD*q_pow(f[i][j], n)) %= MOD; } } ans = (ans + MOD) % MOD; printf("%lld\n", ans); } return 0; }
F
思路:fhq treap。split操作换成按位置split。
代码:
#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include<bits/stdc++.h> using namespace std; #define y1 y11 #define fi first #define se second #define pi acos(-1.0) #define LL long long //#define mp make_pair #define pb emplace_back #define ls rt<<1, l, m #define rs rt<<1|1, m+1, r #define ULL unsigned LL #define pll pair<LL, LL> #define pli pair<LL, int> #define pii pair<int, int> #define piii pair<pii, int> #define pdd pair<double, double> #define mem(a, b) memset(a, b, sizeof(a)) #define debug(x) cerr << #x << " = " << x << "\n"; #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); //head struct fhq_treap { static const int N = 1e5 + 5; struct Node { int val, mx, key, lc, rc, sz; }tree[N]; int rt, tot; inline void init() { rt = tot = 0; tree[rt].sz = tree[rt].val = tree[rt].mx = tree[rt].lc = tree[rt].rc = 0; srand(time(0)); } inline void update(int rt) { tree[rt].mx = max(tree[rt].val, max(tree[tree[rt].lc].mx, tree[tree[rt].rc].mx)); tree[rt].sz = tree[tree[rt].lc].sz + tree[tree[rt].rc].sz + 1; } void split(int rt, int &a, int &b, int x) { if(rt == 0) {a = b = 0; return ;} if(tree[tree[rt].lc].sz+1 <= x) { a = rt; split(tree[rt].rc, tree[a].rc, b, x-tree[tree[rt].lc].sz-1); } else { b = rt; split(tree[rt].lc, a, tree[b].lc, x); } update(rt); } void merge(int &rt, int a, int b) { if(a==0 || b==0) { rt = a+b; return ; } if(tree[a].key < tree[b].key) { rt = a; merge(tree[rt].rc, tree[a].rc, b); } else { rt = b; merge(tree[rt].lc, a, tree[b].lc); } update(rt); } inline int new_node() { tree[++tot].sz = 1; scanf("%d", &tree[tot].val); tree[tot].mx = tree[tot].val; tree[tot].lc = tree[tot].rc = 0; tree[tot].key = rand()*rand(); return tot; } void ins(int &rt) { int node = new_node(); merge(rt, rt, node); } void delete_node(int &rt, int val) { int x = 0, y = 0, z = 0; split(rt, x, y, val); split(x, x, z, val-1); merge(z, tree[z].lc, tree[z].rc); merge(x, x, z); merge(rt, x, y); } inline int get_kth(int rt, int k) { while(tree[tree[rt].lc].sz+1 != k) { if(tree[tree[rt].lc].sz >= k) rt = tree[rt].lc; else k -= tree[tree[rt].lc].sz+1, rt = tree[rt].rc; } return tree[rt].val; } int get_pos(int rt, int x) { if(!rt) return 0; if(tree[tree[rt].lc].mx > x) return get_pos(tree[rt].lc, x); else if(tree[rt].val > x) return tree[tree[rt].lc].sz; else return get_pos(tree[rt].rc, x)+tree[tree[rt].lc].sz+1; } int get_rnk(int &rt, int val) { int x = 0, y = 0; split(rt, x, y, val-1); int tmp = tree[x].sz+1; merge(rt, x, y); return tmp; } int get_pre(int &rt, int val) { int x = 0, y = 0; split(rt, x, y, val-1); int tmp = get_kth(x, tree[x].sz); merge(rt, x, y); return tmp; } int get_scc(int &rt, int val) { int x = 0, y = 0; split(rt, x, y, val); int tmp = get_kth(y, 1); merge(rt, x, y); return tmp; } }t; void solve(int l, int m, int r) { int x = 0, y = 0; t.split(t.rt, x, y, r); t.rt = x; int a = 0, b = 0; t.split(t.rt, a, b, m); t.rt = 0; while(a&&b) { int va = t.get_kth(a, 1), vb = t.get_kth(b, 1); if(va > vb) swap(va, vb), swap(a, b); int p = t.get_pos(a, vb), tmp; t.split(a, tmp, a, p); t.merge(t.rt, t.rt, tmp); } if(a) t.merge(t.rt, t.rt, a); if(b) t.merge(t.rt, t.rt, b); t.merge(t.rt, t.rt, y); } int n, m, op, l, p, r; int main() { t.init(); scanf("%d %d", &n, &m); for (int i = 1; i <= n; ++i) t.ins(t.rt); for (int i = 1; i <= m; ++i) { scanf("%d", &op); if(op == 1) { scanf("%d %d %d", &l, &p, &r); solve(l, p, r); } else { scanf("%d", &p); printf("%d\n", t.get_kth(t.rt, p)); } } return 0; }
G
H
I
思路:后缀数组+回文自动机。
先将原串反转放在原来的串的后面,用后缀数组求出本质不同的串的个数$a$,然后用回文自动机求出本质不同的回文串的个数$b$,然后$\frac{a+b}{2}$就是答案。
队友的板子真丑。
代码:
#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include<bits/stdc++.h> using namespace std; #define y1 y11 #define fi first #define se second #define pi acos(-1.0) #define LL long long //#define mp make_pair #define pb emplace_back #define ls rt<<1, l, m #define rs rt<<1|1, m+1, r #define ULL unsigned LL #define pll pair<LL, LL> #define pli pair<LL, int> #define pii pair<int, int> #define piii pair<pii, int> #define pdd pair<double, double> #define mem(a, b) memset(a, b, sizeof(a)) #define debug(x) cerr << #x << " = " << x << "\n"; #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); const int maxn=4e5+10; char s[maxn]; int y[maxn],x[maxn],c[maxn],sa[maxn],rk[maxn],height[maxn]; int n,m,now,sz; int get_sa() { for (int i=0;i<=m;i++) c[i]=0; for (int i=1;i<=n;++i) ++c[x[i]=s[i]]; for (int i=2;i<=m;++i) c[i]+=c[i-1]; for (int i=n;i>=1;--i) sa[c[x[i]]--]=i; for (int k=1;k<=n;k<<=1) { int num=0; for (int i=n-k+1;i<=n;++i) y[++num]=i; for (int i=1;i<=n;++i) if (sa[i]>k) y[++num]=sa[i]-k; for (int i=1;i<=m;++i) c[i]=0; for (int i=1;i<=n;++i) ++c[x[i]]; for (int i=2;i<=m;++i) c[i]+=c[i-1]; for (int i=n;i>=1;--i) sa[c[x[y[i]]]--]=y[i],y[i]=0; swap(x,y); x[sa[1]]=1;num=1; for (int i=2;i<=n;++i) x[sa[i]]=(y[sa[i]]==y[sa[i-1]] && y[sa[i]+k]==y[sa[i-1]+k]) ? num : ++num; if (num==n) break;m=num; } } int get_height() { int k=0; for (int i=1;i<=n;++i) rk[sa[i]]=i; for (int i=1;i<=n;++i) { if (rk[i]==1) continue;//第一名height为0 if (k) --k;//h[i]>=h[i-1]+1; int j=sa[rk[i]-1]; while (j+k<=n && i+k<=n && s[i+k]==s[j+k]) ++k; height[rk[i]]=k;//h[i]=height[rk[i]]; } } const double eps = 1E-8; const int dx4[4]={1,0,0,-1}; const int dy4[4]={0,-1,1,0}; const int inf = 0x3f3f3f3f; const int N=2e5+7; struct PAM { int fail,cnt,len; int nxt[26]; }st[N]; char RS[N]; string S; void pam_init() { mem(st,0); st[0].fail = st[1].fail = 1; st[1].len = -1; sz = 1; } void extend(int c,int pos) { int p = now; while (S[pos-st[p].len-1]!=S[pos]) p = st[p].fail; if (!st[p].nxt[c]){ int np=++sz,q=st[p].fail; st[np].len=st[p].len+2; while (S[pos-st[q].len-1]!=S[pos]) q=st[q].fail; st[np].fail=st[q].nxt[c]; st[p].nxt[c] = np; } now=st[p].nxt[c]; st[now].cnt++; } int main() { string ss; cin>>ss; int t=ss.size(); S=ss; ss="#"+ss+"#"; reverse(S.begin(), S.end()); ss += S; n=ss.size(); n--; for(int i=1;i<=n;i++) s[i]=ss[i]; m=122; get_sa(); get_height(); LL ans=n*1LL*(n+1)/2-1LL*(t+1)*(t+1); //cout<<ans<<endl; for(int i=1;i<=n;i++) ans-=height[i]; for(int i=0;i<=n;i++) { x[i]=0; y[i]=0; sa[i]=0; rk[i]=0; height[i]=0; } n = S.size(); pam_init(); for ( int i = 0 ; i < n; i++) extend(S[i]-\'a\',i); ans -= sz-1; ans /= 2; ans += sz-1; printf("%lld\n",ans); }
J
思路:分层图最短路
代码:
#include <bits/stdc++.h> 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; template<class T> void _R(T &x) { cin >> x; } void _R(int &x) { scanf("%d", &x); } void _R(ll &x) { scanf("%lld", &x); } void _R(double &x) { scanf("%lf", &x); } void _R(char &x) { scanf(" %c", &x); } void _R(char *x) { scanf("%s", x); } void R() {} template<class T, class... U> void R(T &head, U &... tail) { _R(head); R(tail...); } 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; } const int inf = 0x3f3f3f3f; const ll inff = 0x3f3f3f3f3f3f3f3f; const int mod = 998244353; /**********showtime************/ const int maxn = 1e3+9; vector<pii> mp[maxn]; int dis[maxn][maxn]; int n,m,s, t, k; void bfs(int s) { memset(dis, inf, sizeof(dis)); dis[s][0] = 0; queue<pii>que; que.push(pii(s, 0)); while(!que.empty()){ int u = que.front().fi; int tk = que.front().se; que.pop(); for(pii p : mp[u]) { int v = p.fi, w = p.se; if(tk < k && dis[v][tk+1] > dis[u][tk]) { dis[v][tk+1] = dis[u][tk]; que.push(pii(v, tk+1)); } if(dis[v][tk] > dis[u][tk] + w) { dis[v][tk] = dis[u][tk] + w; que.push(pii(v, tk)); } } } } int main(){ scanf("%d%d%d%d%d", &n, &m, &s, &t, &k); for(int i=1; i<=m; i++) { int u,v,w; scanf("%d%d%d", &u, &v, &w); mp[u].pb(pii(v, w)); mp[v].pb(pii(u, w)); } bfs(s); int ans = inf; for(int i=0; i<=k; i++) { ans = min(ans, dis[t][i]); } printf("%d\n", ans); return 0; }
K
思路:枚举最后两个零,看前面有多少个后缀$mod3$等于0。对于$"00"$和$"0"$的情况,最后统计。
代码:
#include<bits/stdc++.h> using namespace std; const int maxn=1000000; int dp[maxn][20]; char ss[maxn]; int main(){ string ss; cin>>ss; ss="#"+ss; int l=ss.size(); long long ans=0; for(int i=1;i<=l;i++){ int x=ss[i]-\'0\'; dp[i][x%3]++; for(int j=0;j<=2;j++){ dp[i][(j*10+x)%3]+=dp[i-1][j]; } if(i+2 <= l){ if(ss[i+1]==\'0\'&&ss[i+2]==\'0\'){ ans += dp[i][0]; } } } for (int i = 1; i <= l; ++i) { if(ss[i] == \'0\') ans++; if(i-1 >= 1 && ss[i-1] == \'0\' && ss[i] == \'0\') ans++; } cout<<ans<<endl; }
题号 | 标题 | 团队的状态 |
---|---|---|
A | digits 2 | 通过 |
B | generator 1 | 通过 |
C | generator 2 | 通过 |
D | generator 3 | 未通过 |
E | independent set 1 | 通过 |
F | maximum clique 1 | 通过 |
G | subsequence 1 | 通过 |
H | subsequence 2 | 通过 |
I | three points 1 | 通过 |
J | three points 2 | 未通过 |
A
思路:输出n个n。
代码:
#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include<bits/stdc++.h> using namespace std; #define y1 y11 #define fi first #define se second #define pi acos(-1.0) #define LL long long //#define mp make_pair #define pb emplace_back #define ls rt<<1, l, m #define rs rt<<1|1, m+1, r #define ULL unsigned LL #define pll pair<LL, LL> #define pli pair<LL, int> #define pii pair<int, int> #define piii pair<pii, int> #define pdd pair<double, double> #define mem(a, b) memset(a, b, sizeof(a)) #define debug(x) cerr << #x << " = " << x << "\n"; #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); //head int T, n; int main() { scanf("%d", &T); while(T--) { scanf("%d", &n); for (int i = 1; i <= n; ++i) printf("%d", n); printf("\n"); } return 0; }
B
思路:十进制快速幂。
代码:
#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include<bits/stdc++.h> using namespace std; #define y1 y11 #define fi first #define se second #define pi acos(-1.0) #define LL long long #define ll long long //#define mp make_pair #define pb emplace_back #define ls rt<<1, l, m #define rs rt<<1|1, m+1, r #define ULL unsigned LL #define pll pair<LL, LL> #define pli pair<LL, int> #define pii pair<int, int> #define piii pair<pii, int> #define pdd pair<double, double> #define mem(a, b) memset(a, b, sizeof(a)) #define debug(x) cerr << #x << " = " << x << "\n"; #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); const int maxn=1e6+10; //head int MOD; struct Matrix { int a[2][2]; void init() { for (int i = 0; i < 2; i++) { for (int j = 0; j < 2; j++) a[i][j] = 0; } } void _init() { init(); for (int i = 0; i < 2; i++) a[i][i] = 1; } }; Matrix mul(Matrix a, Matrix b) { Matrix ans; ans.init(); for (int i = 0; i < 2; i++) { for (int j = 0; j < 2; j++) { if(a.a[i][j]) { for (int k = 0; k < 2; k++) ans.a[i][k] = (ans.a[i][k] + 1LL * a.a[i][j] * b.a[j][k]) % MOD; } } } return ans; } Matrix q_pow(Matrix a) { Matrix ans; ans._init(); a = mul(a, a); ans = mul(ans, a); a = mul(a, a); a = mul(a, a); ans = mul(ans, a); return ans; } char ss[maxn]; int main() { int x0,x1,a,b; scanf("%d %d %d %d",&x0,&x1,&a,&b); scanf("%s",ss); scanf("%d",&MOD); Matrix c; c.init(); c.a[0][0]=a; c.a[0][1]=b; c.a[1][0]=1; c.a[1][1]=0; Matrix d; d.init(); d.a[0][0]=x1; d.a[0][1]=0; d.a[1][0]=x0; d.a[1][1]=0; Matrix x[10]; for (int i = 0; i < 10; ++i) { if(i == 0) x[i]._init(); else x[i] = mul(x[i-1], c); } c._init(); int l = strlen(ss); for (int i = 0; i < l; ++i) { c = q_pow(c); c = mul(c, x[ss[i]-\'0\']); } c=mul(c,d); printf("%d\n",c.a[1][0]%MOD); return 0; }
C
思路:BSGS。需要预处理。
队友代码:
#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include<bits/stdc++.h> //#define int long long #define ll long long #define LL long long using namespace std; int x,a,b; int p,mod,MOD; int quick(int x,int n){ int ans=1; while(n){ if(n&1) ans=1ll* ans*x%mod; x=1ll*x*x%mod; n=n/2; } return ans; } struct Hash { static const int MOD = 1999997; static const int N = 1e6; int head[MOD + 10], nx[N], top; int hs[N], id[N]; void init() { memset(head, -1, sizeof head); top = 0; } void insert(int x, int y) { int k = x % MOD; hs[top] = x; id[top] = y; nx[top] = head[k]; head[k] = top++; } int find(int x) { int k = x % MOD; for (int i = head[k]; i != -1; i = nx[i]) { if (hs[i] == x) { return id[i]; } } return -1; } }hs; void init(int a,int p){ int m = pow(p,2.0/3.0)+1, s = 1; //cout<<m<<endl; hs.init(); for(int i = 0; i < m; ++i){ hs.insert(s,i); s= (s*1LL*a)%p; } } int BSGS(int a, int b, int p){ int m = pow(p,2.0/3.0)+1, s = b; int t = quick(a, m); int ww=quick(b,mod-2); s = 1; for(int i = 1; i <= p/m+1; ++i){ s = (s*1LL*t)%p; if(hs.find(1ll*s*ww%mod) != -1 ) return i*m-hs.find(1ll*s*ww%mod); } return -1; } int32_t main(){ int T; scanf("%d",&T); while(T--){ ll n; scanf("%lld %d %d %d %d",&n,&x,&a,&b,&p); mod=p; MOD=p; int q; scanf("%d",&q); init(a,p); while(q--){ ll y; scanf("%lld",&y); if(y==x) { printf("0\n"); continue; } if(a==0) { // x b b b b b if(y==b) printf("1\n"); else printf("-1\n"); } else if(a==1){ // x+b x+2*b y=((y-x)%mod+mod)%mod; //cout<<y<<endl; y=y*quick(b,mod-2)%mod; if(1<=y && y<n ) printf("%lld\n",y); else printf("-1\n"); } else { //cout<<"---------"<<endl; y=( 1ll*(a-1)*y%mod+b)%mod*quick( (1ll*(a-1)*x%mod+b)%mod,mod-2)%mod; y=BSGS(a,y,p); if(1<=y && y<=n ) printf("%lld\n",y); else printf("-1\n"); } } } }
D
E
思路:状压dp。有两个优化的地方,用char开数组优化空间,从最低位转移优化时间。
代码:
#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include<bits/stdc++.h> using namespace std; #define y1 y11 #define fi first #define se second #define pi acos(-1.0) #define LL long long //#define mp make_pair #define pb emplace_back #define ls rt<<1, l, m #define rs rt<<1|1, m+1, r #define ULL unsigned LL #define pll pair<LL, LL> #define pli pair<LL, int> #define pii pair<int, int> #define piii pair<pii, int> #define pdd pair<double, double> #define mem(a, b) memset(a, b, sizeof(a)) #define debug(x) cerr << #x << " = " << x << "\n"; #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); //head vector<int> g[26]; int n, m, u, v, st[26]; char dp[(1<<26)+10], mp[(1<<26)+10]; int main() { scanf("%d %d", &n, &m); for (int i = 0; i < m; ++i) { scanf("%d %d", &u, &v); st[u] |= 1<<v; st[v] |= 1<<u; } for (int i = 0; i < n; ++i) st[i] |= 1<<i; int p = 1; for (int i = 0; i < n; ++i) mp[p] = i, p <<= 1; dp[0] = 0; int up = 1<<n, ans = 0; for (int i = 1; i < up; ++i) { int x = i&-i; dp[i] = max(dp[i], dp[i^x]); dp[i] = max(dp[i], (char)(dp[i&(~st[mp[x]])]+1)); ans += dp[i]; } printf("%d\n", ans); return 0; }
F
思路:最大团转换成二分图最大独立集。
队友代码:
// #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 = 998244353; 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 = 5e3+9; int a[maxn]; int col[maxn]; vector<int>L, R; vector<int>mp[maxn]; void dfs(int s, int c) { col[s] = c; for(int i=0; i<mp[s].size(); i++){ int v = mp[s][i]; if(col[v] == 0) dfs(v, 3 - c); } } int vis[maxn],match[maxn],pt[maxn]; bool gkd(int u) { if(vis[u]) return false; vis[u] = true; for(int i = 0; i<mp[u].size(); i++) { int v = mp[u][i]; if(match[v] == -1 || gkd(match[v]) ){ match[v] = u; pt[u] = v; return true; } } return false; } int res[maxn]; bool findmn(int u) { if(u == -1) return false; if(res[u]) return true; // res[u] = 1; if(col[u] == 1){ if(findmn(pt[u])) {res[u] = 1;return true;} else return false; } else { res[u] = 1; for(int i=0; i<mp[u].size(); i++) { int v = mp[u][i]; if(match[u] == v) continue; findmn(v); } return true; } } int main(){ int n; scanf("%d", &n); for(int i=1; i<=n; i++) scanf("%d", &a[i]); for(int i=1; i<=n; i++) { for(int j=i+1; j<=n; j++) { if(__builtin_popcount(a[i] ^ a[j]) == 1) { mp[i].pb(j); mp[j].pb(i); } } } for(int i=1; i<=n; i++) if(col[i] == 0) dfs(i, 1); int cnt = 0; memset(match, -1, sizeof(match)); for(int i=1; i<=n; i++) { memset(vis, 0, sizeof(vis)); if(col[i] == 1 && gkd(i)) cnt++; } printf("%d\n", n-cnt); for(int i=1; i<=n; i++) { if(col[i] == 2 && match[i] == -1) {findmn(i);} } vector<int>ans; for(int i=1; i<=n; i++) { if(col[i] == 1 && res[i] == 0) ans.pb(a[i]); if(col[i] == 2 && res[i] == 1) ans.pb(a[i]); } for(int i=0; i<ans.size(); i++) { printf("%d ", ans[i]); } puts(""); return 0; }
G
思路:dp。
代码:
#include<bits/stdc++.h> #define ll long long using namespace std; const int maxn=3e3+10; const int mod=998244353; int dp[maxn][maxn]; char ss[maxn]; char tt[maxn]; int A[maxn]; int B[maxn]; int quick(int x,int n){ int ans=1; while(n){ if(n&1) ans=1ll*ans*x%mod; x=1ll*x*x%mod; n=n/2; } return ans; } int C(int n,int x){ if(x>n) return 0; return 1ll*A[n]*B[n-x]%mod*B[x]%mod; } int main(){ A[0]=1; B[0]=1; for(int i=1;i<maxn;i++) A[i]=1ll*A[i-1]*i%mod; for(int i=1;i<maxn;i++) B[i]=quick(A[i],mod-2); //cout<<1ll*121321*1354534<<endl; int T; scanf("%d",&T); while(T--){ int ans=0; int n,m; scanf("%d %d",&n,&m); scanf("%s",ss+1); scanf("%s",tt+1); dp[0][0]=1; for(int i=1;i<=n;i++){ if(ss[i]!=\'0\'){ for(int j=m;j<=n-i;j++){ ans+=C(n-i,j); ans=ans%mod; } } for(int j=0;j<=m-1;j++) dp[i][j]=dp[i-1][j]; for(int j=0;j<=m-1;j++){ if(ss[i]==tt[j+1]) { dp[i][j+1]+=dp[i-1][j]; dp[i][j+1]%=mod; } else if(ss[i]>tt[j+1]){ ans+=1ll*dp[i-1][j]*C(n-i,m-j-1)%mod; ans=ans%mod; } } } printf("%d\n",ans); for(int i=0;i<=n+1;i++){ for(int j=0;j<=m+1;j++){ dp[i][j]=0; } } } return 0; }
H
思路:拓扑排序。
代码:
#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include <bits/stdc++.h> 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; 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; } const int inf = 0x3f3f3f3f; const ll inff = 0x3f3f3f3f3f3f3f3f; const int mod = 998244353; /**********showtime************/ const int maxn = 1e4+9; int vis[22], visno[22]; char str[5]; char res[maxn]; int tot = 0; vector<int> mp[22]; vector<int>G[maxn*100]; int pt[maxn*100]; int du[maxn*100]; int id[maxn]; char ans[maxn]; int main(){ int n,m; scanf("%d%d", &n, &m); int cnt = m * (m - 1) / 2; int flag = 1; memset(vis, -1, sizeof(vis)); for(int i=1; i<=cnt; i++) { scanf("%s", str); int len; scanf("%d", &len); if(len == 0) { int dd1 = str[0] - \'a\'; int dd2 = str[1] - \'a\'; visno[dd1] = visno[dd2] = 1; continue;/// } scanf("%s", res); int dd1 = str[0] - \'a\'; int dd2 = str[1] - \'a\'; if(vis[dd1] == -1) { int cc = 0; for(int j = 0; j<len; j++) { if(res[j] == str[0]) { id[j] = ++tot; mp[dd1].pb(tot); pt[tot] = dd1; cc++; } } vis[dd1] = cc; } else { int cc = 0; for(int j=0; j<len; j++) { if(res[j] == str[0]) { if(cc < mp[dd1].size()) id[j] = mp[dd1][cc]; cc++; } } if(cc != vis[dd1])flag = 0; } if(vis[dd2] == -1) { int cc = 0; for(int j = 0; j<len; j++) { if(res[j] == str[1]) { id[j] = ++tot; mp[dd2].pb(tot); pt[tot] = dd2; cc++; } } vis[dd2] = cc; } else { int cc = 0; for(int j=0; j<len; j++) { if(res[j] == str[1]) { if(cc < mp[dd2].size()) id[j] = mp[dd2][cc]; cc++; } } if(cc != vis[dd2])flag = 0; } for(int j=0; j<len-1; j++) { G[id[j]].pb(id[j+1]); du[id[j+1]]++; } } for(int i=0; i<m; i++) { if(vis[i] && visno[i]) flag = 0; } if(!flag || tot != n) puts("-1"); else { // string ans = ""; int all = 0; queue<int>que; for(int i=1; i<=tot; i++) if(du[i] == 0) que.push(i); while(!que.empty()) { int u = que.front(); que.pop(); // ans += pt[u] +\'a\'; ans[all++] = pt[u] + \'a\'; for(int i=0; i<G[u].size(); i++) { int v = G[u][i]; du[v]--; if(du[v] == 0) { que.push(v); } } } int ff = 1; for(int i=1; i<=tot; i++) if(du[i] > 0) ff = 0; if(ff == 0) puts("-1"); else { ans[all] = \'\0\'; printf("%s\n",ans); } } return 0; }
I
思路:暴力枚举每条边的顺序关系。
队友代码:
#include<bits/stdc++.h> using namespace std; const double eps=1e-7; const double pi=acos(-1.0); inline double sqr(double x){ return x*x; } inline int dcmp(double x) { if(fabs(x)<eps) return 0;return (x>0? 1: -1);} struct Point{ double x,y; Point(){ x=0,y=0; } Point(double _x,double _y):x(_x),y(_y){} bool operator ==(const Point &b)const{return ( dcmp(x-b.x)==0&&dcmp(y-b.y)==0); } bool operator !=(const Point &b)const{return !((dcmp(x-b.x)==0&&dcmp(y-b.y)==0)); } bool operator <(const Point &b)const {return (dcmp(x-b.x)==0? dcmp(y-b.y)<0 : x<b.x); } double operator ^(const Point &b)const{ return x*b.y-y*b.x;}//叉积 double operator *(const Point &b)const{ return x*b.x+y*b.y;} //点积 Point operator +(const Point &b)const { return Point(x+b.x,y+b.y);} Point operator -(const Point &b)const { return Point(x-b.x,y-b.y);} Point operator *(double a) { return Point(x*a,y*a); } Point operator /(double a) { return Point(x/a,y/a); } double len2() { return sqr(x)+sqr(y); }//长度平方 double len() { return sqrt(len2()); }//长度 double polar(){ return atan2(y,x); }//向量的极角 //返回与x轴正向夹角(-pi~pi] }X,Y,Z; double dis(Point A,Point B) { return sqrt( (A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y));} struct Circle{ Point c; double r; Circle() {c.x=0; c.y=0; r=0; } Circle(Point c,double r):c(c),r(r) {} Point point(double a){ return Point (c.x+cos(a)*r,c.y+sin(a)*r); } }A,B; int h,w,a,b,c; Point Circle_Cirle(Circle c1, Circle c2){ double d=dis(c1.c,c2.c); Point k=c2.c-c1.c; double a=k.polar(); double da=acos( (c1.r*c1.r+d*d-c2.r*c2.r)/(2*c1.r*d) ); Point p1=c1.point(a-da); //printf("%.10f %.10f\n",p1.x,p1.y); Point p2=c1.point(a+da); // printf("%.10f %.10f\n",p2.x,p2.y); // cout<<h<<" "<<w<<endl; if(-eps<=p1.x && p1.x<=h+eps && p1.y<=w+eps && p1.y>=-eps) return p1; if(-eps<=p2.x && p2.x<=h+eps && p2.y<=w+eps && p2.y>=-eps) return p2; Point p={-1,-1}; return p; } void make(Point &XX,int aa,Point &YY,int bb,Point &ZZ,int cc){ XX.x=0; XX.y=0; if(aa<=h) { YY.x=aa; YY.y=0; } else { double qq=sqrt(1.0*aa*aa-1.0*h*h); YY.x=h; YY.y=qq; } A.c=XX; A.r=cc; B.c=YY; B.r=bb; ZZ=Circle_Cirle(A,B); // cout<<A.c.x<<" "<<A.c.y<<" "<<A.r<<endl; // cout<<B.c.x<<" "<<B.c.y<<" "<<B.r<<endl; // printf("%.10f %.10f %.10f %.10f %.10f %.10f\n",abs(X.x),abs(X.y),abs(Y.x),abs(Y.y),abs(Z.x),abs(Z.y)); } bool check(){ if( abs(dis(X,Y)-a)<eps && abs(dis(X,Z)-b)<eps && abs(dis(Y,Z)-c)<eps && X.x>=-eps && X.x<=h+eps && X.y>=-eps && X.y<=w+eps && Y.x>=-eps && Y.x<=h+eps && Y.y>=-eps && Y.y<=w+eps && Z.x>=-eps && Z.x<=h+eps && Z.y>=-eps && Z.y<=w+eps ) return 1; return 0; } void work(){ X.x=0; X.y=0; Y.x=0; Y.y=0; Z.x=0; Z.y=0; make(X,a,Y,c,Z,b); if(check()) return ; X.x=0; X.y=0; Y.x=0; Y.y=0; Z.x=0; Z.y=0; make(X,b,Z,c,Y,a); if(check()) return ; X.x=0; X.y=0; Y.x=0; Y.y=0; Z.x=0; Z.y=0; make(Y,a,X,b,Z,c); if(check()) return ; X.x=0; X.y=0; Y.x=0; Y.y=0; Z.x=0; Z.y=0; make(Y,c,Z,b,X,a); if(check()) return ; X.x=0; X.y=0; Y.x=0; Y.y=0; Z.x=0; Z.y=0; make(Z,b,X,a,Y,c); if(check()) return ; X.x=0; X.y=0; Y.x=0; Y.y=0; Z.x=0; Z.y=0; make(Z,c,Y,a,X,b); if(check()) return ; } int main(){ int T; scanf("%d",&T); while(T--){ scanf("%d %d %d %d %d",&h,&w,&a,&b,&c); int flag=0; if(h<w) { swap(h,w); flag=1; } work(); if(flag==1){ swap(X.x,X.y); swap(Y.x,Y.y); swap(Z.x,Z.y); } //printf("%.10f\n",dis(X,Y)); //printf("%.10f\n",dis(X,Z)); //printf("%.10f\n",dis(Y,Z)); printf("%.10f %.10f %.10f %.10f %.10f %.10f\n",abs(X.x),abs(X.y),abs(Y.x),abs(Y.y),abs(Z.x),abs(Z.y)); } }
J
题号 | 标题 | 团队的状态 |
---|---|---|
A | Garbage Classification | 通过 |
B | Shorten IPv6 Address | 通过 |
C | Palindrome Mouse | 通过 |
D | Move | 通过 |
E | Androgynos | 通过 |
F | K-ary Heap | 未通过 |
G | Is Today Friday? | 通过 |
H | Train Driver | 通过 |
I | Can They Go to Galar? | 未通过 |
J | Upgrading Technology | 通过 |
A
思路:暴力。
代码:
#include<bits/stdc++.h> using namespace std; const int maxn=2e3+10; char ss[maxn]; char tt[maxn]; map<char,char> mp; int main(){ int T; scanf("%d",&T); int tot=0; while(T--){ scanf("%s",ss); int l=strlen(ss); scanf("%s",tt); int r=strlen(tt); char x=\'a\'; for(int i=0;i<r;i++) { mp[x]=tt[i]; x++; } int a=0; int b=0; int c=0; for(int i=0;i<l;i++){ if(mp[ss[i]]==\'h\') a++; if(mp[ss[i]]==\'d\') b++; if(mp[ss[i]]==\'w\') c++; } if(4*a>=l){ printf("Case #%d: Harmful\n",++tot); } else if(10*a<=l){ printf("Case #%d: Recyclable\n",++tot); } else if(b>=2*c){ printf("Case #%d: Dry\n",++tot); } else { printf("Case #%d: Wet\n",++tot); } mp.clear(); } }
B
思路:注意如果连续的0在最前面或最后面会少一个冒号。
代码:
#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include<bits/stdc++.h> using namespace std; #define y1 y11 #define fi first #define se second #define pi acos(-1.0) #define LL long long //#define mp make_pair #define pb emplace_back #define ls rt<<1, l, m #define rs rt<<1|1, m+1, r #define ULL unsigned LL #define pll pair<LL, LL> #define pli pair<LL, int> #define pii pair<int, int> #define piii pair<pii, int> #define pdd pair<double, double> #define mem(a, b) memset(a, b, sizeof(a)) #define debug(x) cerr << #x << " = " << x << "\n"; #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); //head int T; string s; set<string> st; string x[15]; int l[10]; int main() { fio; cin >> T; for(int cs = 1; cs <= T; ++cs) { cin >> s; int now = 0; for (int i = 0; i < 128; i += 16) { string res = ""; int v = 0; for (int j = i; j < i+16; j ++) { if(j != i && (j-i)%4 == 0) { if(v == 0) { if(res.size() == 0); else res += \'0\'; } else { if(v >= 10) res += char(v-10+\'a\'); else res += char(v+\'0\'); } v = 0; } v = v*2+s[j]-\'0\'; } if(v == 0) { if(res.size() == 0); else res += \'0\'; } else { if(v >= 10) res += char(v-10+\'a\'); else res += char(v+\'0\'); } if(res.size() == 0) res = "0"; x[++now] = res; } int mx = 0; for (int i = 1; i <= now; ++i) { if(x[i] == "0") l[i] = l[i-1]+1; else l[i] = 0; mx = max(mx, l[i]); } if(mx <= 1){ string t = ""; for (int i = 1; i <= now; ++i) { t += x[i]; if(i != now) t += ":"; } st.insert(t); } else { for (int i = 1; i <= now; ++i) { if(l[i] == mx && i-mx != 0 && i != now) { string t = ""; for (int j = 1; j <= i-mx; ++j) { t += x[j]; if(j != i-mx) t += ":"; } t += "::"; for (int j = i+1; j <= now; ++j) { t += x[j]; if(j != now) t += ":"; } st.insert(t); } } if(st.empty()) { for (int i = 1; i <= now; ++i) { if(l[i] == mx) { string t = ""; for (int j = 1; j <= i-mx; ++j) { t += x[j]; if(j != i-mx) t += ":"; } t += "::"; for (int j = i+1; j <= now; ++j) { t += x[j]; if(j != now) t += ":"; } st.insert(t); } } } } cout << "Case #" << cs << ": "<< *(st.begin()) << "\n"; for (int i = 1; i <= now; ++i) l[i] = 0; string().swap(s); st.clear(); } return 0; }
C
思路:回文自动机上乱跳。
队友代码:
#include<bits/stdc++.h> #define ll long long #define LL long long using namespace std; const int maxn=1e5+10; char ss[maxn]; struct PAM{ #define ll long long #define LL long long static const int maxn=3e5+10; static const int num=27; int fail[maxn],cnt[maxn],len[maxn],ch[maxn][num],vis[maxn]; int last,tot; LL ans; void inint(){ last=0; tot=0; fail[0]=fail[1]=1; len[0]=0; len[1]=-1; tot++; ans=0; } int get_fail(int p,int pos){ while(ss[pos-len[p]-1]!=ss[pos]) p=fail[p]; return p; } void add(int x,int pos){ int p=get_fail(last,pos); if(!ch[p][x]){ len[++tot]=len[p]+2; fail[tot]=ch[get_fail(fail[p],pos)][x]; ch[p][x]=tot; } cnt[last=ch[p][x]]++; } void count(){ // bu zhi bu tong hui wen ge shu for(int i=tot;i>=0;i--){ cnt[fail[i]]+=cnt[i]; } } void clear(){ for(int i=0;i<=tot;i++){ fail[i]=0; len[i]=0; cnt[i]=0; vis[i]=0; for(int j=0;j<num;j++) ch[i][j]=0; } last=tot=ans=0; } void dfs(int u,int s){ vector<int> vs; //cout<<"---"<<s<<endl; for(int i=fail[u];i>=1;i=fail[i]){ if(vis[i]==1) break; s++; vis[i]=1; vs.push_back(i); } ans+=s;// cout<<s<<endl; if(vis[u]==0) { vis[u]=1; s++; } for(int i=0;i<26;i++){ if(ch[u][i]){ dfs(ch[u][i],s); } } if(u!=0 && u!=1) vis[u]=0; for(int i=0;i<vs.size();i++) vis[vs[i]]=0; } void work(){ vis[0]=1; vis[1]=1; //cout<<ans<<endl; dfs(0,0); dfs(1,0); } }pam; int main(){ int T; scanf("%d",&T); int tot=0; while(T--){ scanf("%s",ss); int l=strlen(ss); pam.inint(); for(int i=0;i<l;i++) pam.add(ss[i]-\'a\',i); pam.work(); printf("Case #%d: %lld\n",++tot,pam.ans); pam.clear(); } }
D
思路:算一个下界,暴力计算。
代码:
#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include<bits/stdc++.h> using namespace std; #define y1 y11 #define fi first #define se second #define pi acos(-1.0) #define LL long long //#define mp make_pair #define pb emplace_back #define ls rt<<1, l, m #define rs rt<<1|1, m+1, r #define ULL unsigned LL #define pll pair<LL, LL> #define pli pair<LL, int> #define pii pair<int, int> #define piii pair<pii, int> #define pdd pair<double, double> #define mem(a, b) memset(a, b, sizeof(a)) #define debug(x) cerr << #x << " = " << x << "\n"; #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); //head const int N = 1e3 + 5; vector<int> vc; int v[N], T, n, k; multiset<int> a, b; int main() { scanf("%d", &T); for (int cs = 1; cs <= T; ++cs) { scanf("%d %d", &n, &k); for (int i = 1; i <= n; ++i) scanf("%d", &v[i]), a.insert(v[i]); int sum = 0, mx = 0; for (int i = 1; i <= n; ++i) sum += v[i], mx = max(mx, v[i]); int dw = max(mx, (sum+k-1)/k); for (int i = dw; ; ++i) { int tt = 0, now = 0, up = i; b = a; while(!b.empty()) { auto t = b.upper_bound(up-now); if(t == b.begin()) { now = 0; ++tt; } else { --t; now += *t; b.erase(b.find(*t)); } } if(now) ++tt; if(tt <= k) { printf("Case #%d: %d\n", cs, up); break; } } a.clear(); b.clear(); } return 0; }
E
思路:4个一起构造,最后如果剩下5个单独构造。
代码:
#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include <bits/stdc++.h> 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; 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; } const int inf = 0x3f3f3f3f; const ll inff = 0x3f3f3f3f3f3f3f3f; const int mod = 998244353; /**********showtime************/ const int maxn = 2009; int mp[maxn][maxn]; int pt[maxn]; void solve(int le, int ri) { if(ri - le + 1 == 5) { for(int i=le; i<ri; i++) { mp[i+1][i] = mp[i][i+1] = 1; pt[i] = i+1; } mp[le][ri] = mp[ri][le] = 1; pt[le] = le; pt[le+1] = le+2; pt[ri] = ri-1; pt[le+2] = ri; pt[le+3] = le+1; } else if(ri - le + 1 == 4) { mp[le][le+2] = mp[le+2][le] = 1; mp[le][le+1] = mp[le+1][le] = 1; mp[le+1][le+3] = mp[le+3][le+1] = 1; pt[le] = le + 2; pt[le+1] = le + 3; pt[le+2] = le+1; pt[le+3] = le; } else { mp[le][le+2] = mp[le+2][le] = 1; mp[le][le+1] = mp[le+1][le] = 1; mp[le+1][le+3] = mp[le+3][le+1] = 1; pt[le] = le + 2; pt[le+1] = le + 3; pt[le+2] = le+1; pt[le+3] = le; for(int i= le+4; i<=ri; i++) { mp[le+2][i] = 1; mp[i][le+2] = 1; mp[le+3][i] = 1; mp[i][le+3] = 1; } solve(le+4, ri); } } int main(){ int T; scanf("%d", &T); int cas = 0; while(T--) { int n; scanf("%d", &n); if(n == 1) { printf("Case #%d: Yes\n", ++cas); printf("0\n1\n"); } else if(n < 4) printf("Case #%d: No\n", ++cas); else { if(n * (n-1) % 4) printf("Case #%d: No\n", ++cas); else { printf("Case #%d: Yes\n", ++cas); for(int i=1; i<=n; i++) { for(int j=1; j<=n; j++) mp[i][j] = 0; pt[i] = 0; } solve(1, n); for(int i=1; i<=n; i++) { for(int j=1; j<=n; j++) { printf("%d",mp[i][j]); } puts(""); } for(int i=1; i<n; i++) printf("%d ", pt[i]); printf("%d\n", pt[n]); } } } return 0; }
F
G
思路:暴力枚举排列,然后判断每一个是否可以(用蔡勒公式),由于存在的情况很少,所以判断只要很少就能退出。除了一种情况,一直都是可以的,
但是本质不同的可以的很少,所以这种情况肯定有很多重复的。所以暴力前先去个重。
代码:
#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include<bits/stdc++.h> using namespace std; #define y1 y11 #define fi first #define se second #define pi acos(-1.0) #define LL long long //#define mp make_pair #define pb emplace_back #define ls rt<<1, l, m #define rs rt<<1|1, m+1, r #define ULL unsigned LL #define pll pair<LL, LL> #define pli pair<LL, int> #define pii pair<int, int> #define piii pair<pii, int> #define pdd pair<double, double> #define mem(a, b) memset(a, b, sizeof(a)) #define debug(x) cerr << #x << " = " << x << "\n"; #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); //head int T, n; vector<string> s; int a[10]; int month[2][12] = { {31,28,31,30,31,30,31,31,30,31,30,31}, {31,29,31,30,31,30,31,31,30,31,30,31} }; inline bool ck(int x) { return (x%4==0&&x%100!=0) || x%400==0; } inline int caile(int x, int y, int z) { if(x < 1600) return 0; if(y > 12 || y == 0) return 0; if(ck(x)) { if(z == 0 || z > month[1][y-1]) return 0; } else { if(z == 0 || z > month[0][y-1]) return 0; } if(y <= 2) y += 12, x--; return ((x/100/4-2*(x/100)+x%100+x%100/4+26*(y+1)/10+z-1)%7+7)%7; } int main() { fio; cin >> T; for (int cs = 1; cs <= T; ++cs) { cin >> n; s.resize(n); for (int i = 0; i < n; ++i) cin >> s[i]; sort(s.begin(), s.end()); s.erase(unique(s.begin(), s.end()), s.end()); for (int i = 0; i < 10; ++i) a[i] = i; bool ok = false; do { bool f = true; for (int i = 0; i < s.size(); ++i) { int x = 0, y = 0, z = 0; for (int j = 0; j < 4; ++j) x = x*10 + a[s[i][j]-\'A\']; for (int j = 5; j < 7; ++j) y = y*10 + a[s[i][j]-\'A\']; for (int j = 8; j < 10; ++j) z = z*10 + a[s[i][j]-\'A\']; if(caile(x, y, z) == 5) ; else { f = false; break; } } if(f) { ok = true; cout << "Case #" << cs << ": "; for (int i = 0; i < 10; ++i) cout << a[i]; cout << "\n"; break; } else continue; }while(next_permutation(a, a+10)); if(!ok) cout << "Case #" << cs << ": Impossible\n"; } return 0; }
H
思路:先用bfs预处理每个$a$集合和$b$集合的点到其他点的最短距离。然后枚举$a$集合的点$x$和$b$集合的点$y$,把每个点到$x$的距离和到$y$的距离加起来作为初始值,
然后来更新其他点的最短距离,由于不能有$logn$的复杂度,所以要先对距离哈希排序,然后用两个队列来更新,每次取两个队列队首最小值更新。
代码:
#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include<bits/stdc++.h> using namespace std; #define y1 y11 #define fi first #define se second #define pi acos(-1.0) #define LL long long //#define mp make_pair #define pb emplace_back #define ls rt<<1, l, m #define rs rt<<1|1, m+1, r #define ULL unsigned LL #define pll pair<LL, LL> #define pli pair<LL, int> #define pii pair<int, int> #define piii pair<pii, int> #define pdd pair<double, double> #define mem(a, b) memset(a, b, sizeof(a)) #define debug(x) cerr << #x << " = " << x << "\n"; #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); //head const int N = 1e5 + 5; int T, n, m, u, v; vector<int> g[N], vc[N*2]; int a[22], b[22], da[22][N], db[22][N], ca, cb; int q[N*2], l1, r1, l2, r2, dis[N]; pii q1[N*2], q2[N*2]; inline void bfs(int u, int *dis) { for (int i = 1; i <= n; ++i) dis[i] = -1; dis[u] = 0; int l = 1, r = 0; q[++r] = u; while(l <= r) { int u = q[l++]; for (int v : g[u]) { if(~dis[v]) ; else dis[v] = dis[u]+1, q[++r] = v; } } } inline LL solve(int x, int y) { LL ans = 0; for (int i = 1; i <= n; ++i) vc[da[x][i]+db[y][i]].pb(i), dis[i] = -1; int l1 = 1, r1 = 0, l2 = 1, r2 = 0; for (int i = 0; i <= 2*n; ++i) {for (int u : vc[i]) q1[++r1] = {i, u}; vc[i].clear();} while(l1 <= r1 || l2 <= r2) { if(l1 <= r1 && l2 <= r2) { if(q1[l1].fi < q2[l2].fi) { int d = q1[l1].fi, u = q1[l1].se; ++l1; if(~dis[u]) continue; dis[u] = d; for (int v : g[u]) if(dis[v] == -1) q2[++r2] = {d+1, v}; } else { int d = q2[l2].fi, u = q2[l2].se; ++l2; if(~dis[u]) continue; dis[u] = d; for (int v : g[u]) if(dis[v] == -1) q2[++r2] = {d+1, v}; } } else if(l1 <= r1) { int d = q1[l1].fi, u = q1[l1].se; ++l1; if(~dis[u]) continue; dis[u] = d; for (int v : g[u]) if(dis[v] == -1) q2[++r2] = {d+1, v}; } else { int d = q2[l2].fi, u = q2[l2].se; ++l2; if(~dis[u]) continue; dis[u] = d; for (int v : g[u]) if(dis[v] == -1) q2[++r2] = {d+1, v}; } } for (int i = 1; i <= n; ++i) ans += dis[i]; return ans; } int main() { scanf("%d", &T); for (int cs = 1; cs <= T; ++cs) { scanf("%d %d", &n, &m); for (int i = 1; i <= m; ++i) scanf("%d %d", &u, &v), g[u].pb(v), g[v].pb(u); scanf("%d", &ca); for (int i = 1; i <= ca; ++i) scanf("%d", &a[i]); scanf("%d", &cb); for (int i = 1; i <= cb; ++i) scanf("%d", &b[i]); for (int i = 1; i <= ca; ++i) bfs(a[i], da[i]); for (int i = 1; i <= cb; ++i) bfs(b[i], db[i]); LL ans = 0; for (int i = 1; i <= ca; ++i) { for (int j = 1; j <= cb; ++j) { LL t = solve(i, j); ans += t; } } LL d = ca*1LL*cb*1LL*n; LL dd = __gcd(d, ans); d /= dd, ans /= dd; printf("Case #%d: %lld/%lld\n", cs, ans, d); for (int i = 1; i <= n; ++i) g[i].clear(); } return 0; }
I
J
思路:注意如果要最多达到$level_i$,至少有一个技能正好是$lelel_i$。
代码:
/* * @Author: chenkexing * @Date: 2019-08-02 20:30:39 * @Last Modified by: chenkexing * @Last Modified time: 2019-08-02 22:33:17 */ // #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 = 998244353; 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 = 1009; ll a[maxn][maxn]; ll sum[maxn][maxn]; ll ss[maxn][maxn]; ll b[maxn]; int main(){ int T; scanf("%d", &T); int cas = 0; while(T--) { int n,m; scanf("%d%d", &n, &m); for(int i=1; i<=n; i++) { for(int j=1; j<=m; j++) { scanf("%lld", &a[i][j]); } } for(int i=0; i<=n; i++) { for(int j=0; j<=m; j++) { sum[i][j] = ss[i][j] = 0; } } for(int i=1; i<=m; i++) scanf("%lld", &b[i]); for(int i=1; i<=n; i++) { for(int j=1; j<=m; j++) sum[i][j] = sum[i][j-1] + a[i][j], ss[i][j] = sum[i][j]; for(int j=m-1; j>=0; j--) sum[i][j] = min(sum[i][j], sum[i][j+1]); } ll ans = 0, allb = 0; for(int i=0; i<=m; i++) { ll tmp = 0; allb += b[i]; for(int j=1; j<=n; j++) { tmp += sum[j][i]; } for(int j=1; j<=n; j++) { tmp -= sum[j][i]; tmp += ss[j][i]; ans = max(ans, allb - tmp); tmp += sum[j][i]; tmp -= ss[j][i]; } } printf("Case #%d: %lld\n",++cas, ans); } return 0; }
题号 | 标题 | 团队的状态 |
---|---|---|
A | String | 通过 |
B | Irreducible Polynomial | 通过 |
C | Governing sand | 通过 |
D | Number | 通过 |
E | Find the median | 通过 |
F | Energy stones | 未通过 |
G | Make Shan Happy | 未通过 |
H | Pair | 通过 |
I | Chessboard | 未通过 |
J | A+B problem | 通过 |
K | Function | 未通过 |
A
思路:$O(n^3)$的dp加最小表示法。
代码:
#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include<bits/stdc++.h> using namespace std; #define y1 y11 #define fi first #define se second #define pi acos(-1.0) #define LL long long //#define mp make_pair #define pb emplace_back #define ls rt<<1, l, m #define rs rt<<1|1, m+1, r #define ULL unsigned LL #define pll pair<LL, LL> #define pli pair<LL, int> #define pii pair<int, int> #define piii pair<pii, int> #define pdd pair<double, double> #define mem(a, b) memset(a, b, sizeof(a)) #define debug(x) cerr << #x << " = " << x << "\n"; #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); //head string s; int Min(string s) { int i = 0, j = 1, k = 0, n = s.size(), d; while(i < n && j < n && k < n) { d = s[(i+k)%n] - s[(j+k)%n]; if(!d) k++; else { if(d > 0) i += k+1; else j += k+1; if(i == j) j++; k = 0; } } return min(i, j); } const int N = 222; int T, dp[N], pre[N], can[N][N]; int main() { fio; cin >> T; while(T--) { cin >> s; int n = s.size(); for (int i = 0; i <= n; ++i) dp[i] = 2*n; for (int i = 1; i <= n; ++i) { string t = ""; for (int j = i; j <= n; ++j) { t += s[j-1]; if(Min(t) == 0) can[i][j] = 1; else can[i][j] = 0; } } dp[0] = 1; for (int i = 1; i <= n; ++i) { for (int j = 0; j < i; ++j) { if(dp[j] && can[j+1][i] && dp[j]+1 <= dp[i]) { dp[i] = dp[j]+1; pre[i] = j; } } } vector<int> vc; int now = n; vc.pb(n); while(pre[now]) { now = pre[now]; vc.pb(now); } vc.pb(0); reverse(vc.begin(), vc.end()); for (int i = 1; i < vc.size(); ++i) { for (int j = vc[i-1]; j < vc[i]; ++j) cout << s[j]; if(i+1 != vc.size())cout << " "; } cout << endl; } return 0; }
B
思路:因为三次及以上实系数多项式至少有一个实零点,所以它可以分解。
代码:
#include<bits/stdc++.h> #define ll long long using namespace std; const int maxn=13; int a[maxn]; int main(){ int T; scanf("%d",&T); while(T--){ int n; scanf("%d",&n); for(int i=n;i>=0;i--){ scanf("%d",&a[i]); } if(n>2) printf("No\n"); else if(n<2) printf("Yes\n"); else { long long c=a[1]*a[1]-4*a[2]*a[0]; if(c<0) printf("Yes\n"); else printf("No\n"); } } }
C
思路:暴力
代码:
// #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 = 1e5+9; struct E{ ll h,c,p; }a[maxn]; bool cmp(E a, E b) { return a.h < b.h; } ll sum[maxn]; ll jilu[209]; int main(){ int n; while(~scanf("%d", &n)) { ll ans = inff; for(int i=1; i<=n; i++) { scanf("%lld%lld%lld", &a[i].h, &a[i].c, &a[i].p); } sort(a+1, a+1+n, cmp); sum[n+1] = 0; for(int i=n; i>=1; i--) { sum[i] = sum[i+1] + 1ll*a[i].c * a[i].p; } for(int i=0; i<209; i++) jilu[i] = 0; a[n+1].h = inf; int las = 1; ll cnt = 0; for(int i=1; i<=n; i++) { if(a[i].h < a[i+1].h) { cnt += a[i].p; ll tmp = sum[i+1]; ll baoliu = 0; ll cc = cnt - 1; for(int j=202; j>=0 && cc; j--) { ll yong = min(jilu[j], cc); baoliu += yong * j; cc -= yong; } tmp = tmp + sum[1] - sum[las] - baoliu; // debug(tmp); ans = min(ans, tmp); for(int j=las; j<=i; j++) jilu[a[j].c] += a[i].p; las = i+1; cnt = 0; } else { cnt += a[i].p; } } printf("%lld\n", ans); } return 0; }
D
思路:看位数够不够,够的话输出一个,后面补0,否则就是不可以。
代码:
#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include<bits/stdc++.h> using namespace std; #define y1 y11 #define fi first #define se second #define pi acos(-1.0) #define LL long long //#define mp make_pair #define pb emplace_back #define ls rt<<1, l, m #define rs rt<<1|1, m+1, r #define ULL unsigned LL #define pll pair<LL, LL> #define pli pair<LL, int> #define pii pair<int, int> #define piii pair<pii, int> #define pdd pair<double, double> #define mem(a, b) memset(a, b, sizeof(a)) #define debug(x) cerr << #x << " = " << x << "\n"; #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); //head LL n, p; int main() { scanf("%lld %lld", &n, &p); LL t = p; int cnt = 0; while(t) t /= 10, ++cnt; if(n >= cnt) { for (int i = 0; i < n/cnt; ++i) printf("%lld", p); for (int i = 0; i < n%cnt; ++i) printf("0"); printf("\n"); } else printf("T_T\n"); return 0; }
E
思路:离散化+线段树
代码:
#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++; 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\n", query((all + 1)/2, 1, tot, 1)); } return 0; }
F
G
H
思路:数位dp
代码:
/* * @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 ^的 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\n", dfs(len, 1, 1, 0, 0, 0, 0)); } return 0; }
I
J
思路:水题
代码:
// #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 ans[maxn]; int shu[maxn]; ll f(ll val) { int len = 0; while(val > 0 && val % 10 == 0) val /= 10; while(val > 0) { shu[++len] = val % 10; val = val / 10; } ll res = 0; for(int i=1; i<=len; i++) { res = res * 10 + shu[i]; } return res; } int main(){ int T; scanf("%d", &T); while(T--) { ll a, b; scanf("%lld%lld", &a, &b); printf("%lld\n", f(f(a) + f(b))); } return 0; }
K
题号 | 标题 | 团队的状态 |
---|---|---|
A | All-one Matrices | 通过 |
B | Beauty Values | 通过 |
C | CDMA | 通过 |
D | Distance | 通过 |
E | Explorer | 通过 |
F | Flower Dance | 通过 |
G | Gemstones | 通过 |
H | How Many Schemes | 未通过 |
I | Inner World | 通过 |
J | Just Jump | 通过 |
A
思路:一个左上角的点和右边界三个值可以确定一个矩阵,然后unorded_map去重被卡,最后用手写bitmap过了(因为bool是一个字节的开不下,bitset也开不下)。正解是单调栈。
bitmap代码:
#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include<bits/stdc++.h> using namespace std; #define y1 y11 #define fi first #define se second #define pi acos(-1.0) #define LL long long //#define mp make_pair #define pb emplace_back #define ls rt<<1, l, m #define rs rt<<1|1, m+1, r #define ULL unsigned LL #define pll pair<LL, LL> #define pli pair<LL, int> #define pii pair<int, int> #define piii pair<pii, int> #define pdd pair<double, double> #define mem(a, b) memset(a, b, sizeof(a)) #define debug(x) cerr << #x << " = " << x << "\n"; #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); //head const int N = 3e3 + 5; const int MOD = 2e9 + 7; short l[N][N], r[N][N], up[N][N]; int n, m; class BitMap { public: BitMap(int num):n(num),mask(0x1F),shift(5),pos(1<<mask),a(1+n/32,0){} void set(int i) { a[i>>shift] |= (pos>>(i & mask)); } int get(int i) { return a[i>>shift] & (pos>>(i & mask)); } void clr(int i) { a[i>>shift] &= ~(pos>>(i & mask)); } private: int n; const int mask; const int shift; const unsigned int pos; vector<unsigned int> a; }; char s[N][N]; BitMap vis(MOD); int main() { scanf("%d %d",&n, &m); for (int i = 1; i <= n; ++i) scanf("%s", s[i]+1); for (int i = 1; i <= n; ++i) { for (int j = 1; j <= m; ++j) { if(s[i][j] == \'1\') l[i][j] = l[i][j-1]+1; } for (int j = m; j >= 1; --j) { if(s[i][j] == \'1\') r[i][j] = r[i][j+1]+1; } } int ans = 0; for (int i = 1; i <= n; ++i) { for (int j = 1; j <= m; ++j) { if(s[i][j] == \'1\') { up[i][j] = up[i-1][j]+1; if(s[i-1][j] == \'1\') { l[i][j] = min(l[i-1][j], l[i][j]); r[i][j] = min(r[i-1][j], r[i][j]); } LL X = i-up[i][j]+1, Y = j-l[i][j]+1, Z = j+r[i][j]-1; LL t = (X*3021*3021+Y*3021+Z)%MOD; //cout << X << " "<< Y << " " << Z << endl; if(!vis.get(t)) vis.set(t), ans++; } } } printf("%d\n", ans); return 0; }
正解代码:
// #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 = 3009; char str[maxn][maxn]; int sum[maxn][maxn]; int dp[maxn][maxn]; int ls[maxn]; stack<pii>st; int main(){ int n,m; scanf("%d%d", &n, &m); for(int i=1; i<=n; i++) scanf("%s", str[i] + 1); for(int i=1; i<=n; i++) { for(int j=1; j<=m; j++) { sum[i][j] = sum[i][j-1]; if(str[i][j] == \'1\') sum[i][j] ++; } } for(int i=n; i>=1; i--) { for(int j=1; j<=m; j++) { if(str[i][j] == \'1\') dp[i][j] = dp[i+1][j] + 1; else dp[i][j] = 0; } } int ans = 0; for(int i=1; i<=n; i++) { // debug(i); while(!st.empty()) st.pop(); st.push(pii(-1, 0)); for(int j=1; j<=m; j++) { while(!st.empty() && st.top().fi >= dp[i][j]) { st.pop(); } ls[j] = st.top().se + 1; st.push(pii(dp[i][j], j)); } while(!st.empty()) st.pop(); for(int j=1; j<=m + 1; j++) { while(!st.empty() && st.top().fi > dp[i][j]) { int le = ls[st.top().se], ri = j - 1; st.pop(); if(sum[i-1][ri] - sum[i-1][le-1] == ri - le + 1) continue; ans++; } if(j < m + 1 && (st.empty() || dp[i][j] > st.top().fi) )st.push(pii(dp[i][j], j)); } } printf("%d\n", ans); return 0; }
B
思路:考虑每个位置的贡献
代码:
/* * @Author: chenkexing * @Date: 2019-08-10 12:07:44 * @Last Modified by: chenkexing * @Last Modified time: 2019-08-10 12:14:56 */ // #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 = 1e5+9; int a[maxn]; int pre[maxn], las[maxn]; int le[maxn],ri[maxn]; int main(){ int n; scanf("%d", &n); for(int i=1; i<=n; i++) scanf("%d", &a[i]), las[i] = n + 1; ll sum = 0; for(int i=1; i<=n; i++) { le[i] = pre[a[i]] + 1; sum = sum + 1ll*(i - le[i] + 1) * (n - i + 1); pre[a[i]] = i; } printf("%lld\n", sum); return 0; }
C
思路:构造。左上角、右上角、左下角原矩阵,右下角相反矩阵。cf原题。
代码:
#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include<bits/stdc++.h> using namespace std; #define y1 y11 #define fi first #define se second #define pi acos(-1.0) #define LL long long //#define mp make_pair #define pb push_back #define ls rt<<1, l, m #define rs rt<<1|1, m+1, r #define ULL unsigned LL #define pll pair<LL, LL> #define pli pair<LL, int> #define pii pair<int, int> #define piii pair<pii, int> #define pdd pair<double, double> #define mem(a, b) memset(a, b, sizeof(a)) #define debug(x) cerr << #x << " = " << x << "\n"; #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); //head int dp[1055][1055]; int main() { dp[0][0]=1; int t=10; int c=1; while(t--) { for(int i=0;i<c;i++) { for(int j=0;j<c;j++) { dp[i][j+c]=dp[i][j]; dp[i+c][j]=dp[i][j]; dp[i+c][j+c]=-dp[i][j]; } } c<<=1; } int m; scanf("%d", &m); for (int i = 0; i < m; ++i) { for(int j = 0; j < m; ++j) printf("%d%c", dp[i][j], " \n"[j+1==m]); } return 0; }
D
思路:定期重构
队友代码:
/* * @Author: chenkexing * @Date: 2019-08-11 21:48:52 * @Last Modified by: chenkexing * @Last Modified time: 2019-08-11 23:23:57 */ // #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<int, pii> p3; 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 = 1e5+9; int n,m,h,q; int getid(int x, int y, int z) { return (z - 1)* (n * m) + (x-1)*m + y; } vector<int>vx,vy,vz; int dis[maxn]; int xia[8][3] = {{0,0,1},{0,1,0},{1,0,0}, {-1, 0 ,0 }, {0, -1 ,0 }, {0, 0 ,-1 }}; void rebuild(){ queue< p3>que; for(int i=0; i<vx.size(); i++) { int nx = vx[i]; int ny = vy[i]; int nz = vz[i]; dis[getid(nx, ny, nz)] = 0; que.push(p3(nx, pii(ny, nz))); } vx.clear(); vy.clear(); vz.clear(); while(!que.empty()) { p3 tmp = que.front(); que.pop(); int x = tmp.fi; int y = tmp.se.fi; int z = tmp.se.se; for(int i=0; i<6; i++) { int nx = x + xia[i][0]; int ny = y + xia[i][1]; int nz = z + xia[i][2]; if(nx <= 0 || nx > n || ny <= 0|| ny > m || nz <= 0 || nz > h) continue; if(dis[getid(nx, ny, nz)] > dis[getid(x, y, z)] + 1) { dis[getid(nx, ny, nz)] = dis[getid(x, y, z)] + 1; que.push(p3(nx, pii(ny, nz))); } } } } int main(){ scanf("%d%d%d%d", &n, &m, &h, &q); int E = sqrt(n * m * h) + 1; memset(dis, inf, sizeof(dis)); while(q--) { int op, x, y, z; scanf("%d%d%d%d", &op, &x, &y, &z); if(op == 1) { vx.pb(x); vy.pb(y); vz.pb(z); } else { int ans = dis[getid(x, y, z)]; for(int i=0; i<vx.size(); i++) { int nx = vx[i]; int ny = vy[i]; int nz = vz[i]; ans = min(ans, abs(nx - x) + abs(ny - y) + abs(nz - z)); } printf("%d\n", ans); } if(vx.size() >= E) rebuild(); } return 0; }
E
思路:按sz分治,把边按sz放到划分树上,然后分治,用可撤销并查集维护连通性。和P2147 [SDOI2008]洞穴勘测类似。
代码:
#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include<bits/stdc++.h> using namespace std; #define y1 y11 #define fi first #define se second #define pi acos(-1.0) #define LL long long //#define mp make_pair #define pb push_back #define ls rt<<1, l, m #define rs rt<<1|1, m+1, r #define ULL unsigned LL #define pll pair<LL, LL> #define pli pair<LL, int> #define pii pair<int, int> #define piii pair<pii, int> #define pdd pair<double, double> #define mem(a, b) memset(a, b, sizeof(a)) #define debug(x) cerr << #x << " = " << x << "\n"; #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); //head const int N = 1e5 + 5; struct UFS { stack<pair<int*, int>> stk; int fa[N], rnk[N]; inline void init(int n) { for (int i = 0; i <= n; ++i) fa[i] = i, rnk[i] = 0; } inline int Find(int x) { while(x^fa[x]) x = fa[x]; return x; } inline void Merge(int x, int y) { x = Find(x), y = Find(y); if(x == y) return ; if(rnk[x] <= rnk[y]) { stk.push({fa+x, fa[x]}); fa[x] = y; if(rnk[x] == rnk[y]) { stk.push({rnk+y, rnk[y]}); rnk[y]++; } } else { stk.push({fa+y, fa[y]}); fa[y] = x; } } inline void Undo() { *stk.top().fi = stk.top().se; stk.pop(); } }ufs; struct Node { int u, v, l, r; }a[N]; int n, m, ans; vector<pii> vc[N<<3]; vector<int> vv; void update(int L, int R, pii p, int rt, int l, int r) { if(L <= l && r <= R) { vc[rt].pb(p); return ; } int m = l+r >> 1; if(L <= m) update(L, R, p, ls); if(R > m) update(L, R, p, rs); } inline int get_id(int x) { return lower_bound(vv.begin(), vv.end(), x)-vv.begin(); } void dfs(int rt, int l, int r) { int sz = ufs.stk.size(); for (pii p : vc[rt]) ufs.Merge(p.fi, p.se); if(l == r){ if(ufs.Find(1) == ufs.Find(n)) ans += vv[l+1]-vv[l]; while(ufs.stk.size() > sz) ufs.Undo(); return ; } int m = l+r >> 1; dfs(ls); dfs(rs); while(ufs.stk.size() > sz) ufs.Undo(); } int main() { scanf("%d %d", &n, &m); for (int i = 1; i <= m; ++i) scanf("%d %d %d %d", &a[i].u, &a[i].v, &a[i].l, &a[i].r), ++a[i].r, vv.pb(a[i].l), vv.pb(a[i].r); sort(vv.begin(), vv.end()); vv.erase(unique(vv.begin(), vv.end()), vv.end()); int tot = vv.size(); for (int i = 1; i <= m; ++i) { update(get_id(a[i].l), get_id(a[i].r)-1, {a[i].u, a[i].v}, 1, 0, tot-2); } ufs.init(n); dfs(1, 0, tot-2); printf("%d\n", ans); return 0; }
F
思路:枚举中心点,然后极角排序,然后将中心点看成原点,然后三角形的三个点只有两种情况:x轴上面2个点,下面1个点,x轴上面1个点,下面2个点
队友代码:
#include<bits/stdc++.h> using namespace std; struct Point{ double x,y; double t; Point(){ x=0,y=0; } Point(double _x,double _y):x(_x),y(_y){} double operator ^(const Point &b)const{ return x*b.y-y*b.x;}//叉积 double operator *(const Point &b)const{ return x*b.x+y*b.y;} //点积 Point operator +(const Point &b)const { return Point(x+b.x,y+b.y);} Point operator -(const Point &b)const { return Point(x-b.x,y-b.y);} Point operator *(double a) { return Point(x*a,y*a); } Point operator /(double a) { return Point(x/a,y/a); } double polar(){ return atan2(y,x); }//向量的极角 //返回与x轴正向夹角(-pi~pi] }; inline double cross(Point a,Point b) { return a.x*b.y-a.y*b.x; } //叉积 #define ll long long const int maxn=1e3+10; const double eps=1e-12; Point a[maxn]; Point b[maxn]; int s[maxn]; int n; ll ans=0; bool cmp1(Point a, Point b)//先按象限排序,再按极角排序,再按远近排序 { if (a.y == 0 && b.y == 0 && a.x*b.x <= 0)return a.x>b.x; if (a.y == 0 && a.x >= 0 && b.y != 0)return true; if (b.y == 0 && b.x >= 0 && a.y != 0)return false; if (b.y*a.y <= 0)return a.y>b.y; Point one; one.y = one.x = 0; return cross(one-a,one-b) > 0 || (cross(one-a,one-b) == 0 && a.x < b.x); } void slove(int x){ for(int i=1;i<=n;i++) { b[i]=a[i]; if(i==x) swap(b[i],b[1]); } for(int i=2;i<=n;i++) { b[i]=b[i]-a[x]; if(fabs(b[i].x)<eps) b[i].x=fabs(b[i].x); if(fabs(b[i].y)<eps) b[i].y=fabs(b[i].y); } for(int i=1;i<=n;i++) { b[i].t= b[i].polar(); } sort(b+2,b+1+n,cmp1); int c=n; while(c>1 && b[c].y<=0 ) c--; memset(s,0,sizeof(s)); int temp=0; int j=c; for(int i=n;i>c;i--){ while(j>1 && (b[i]^b[j])<0 ) { j--; temp++; } s[i]=s[i+1]+temp; } j=c+1; for(int i=2;i<=c;i++){ while(j<=n && (b[i]^b[j])>0 ) { j++; } int num=j; while(j<=n && (b[i]^b[j])>=0) { j++; } ans+=(n-j+1)*(num-c-1)+s[j]; j=num; } } int main(){ //printf("%.10f",atan2(0.0000000000,-1000000000.0) ); scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%lf %lf",&a[i].x,&a[i].y); for(int i=1;i<=n;i++) { slove(i); } printf("%lld\n",ans); }
G
思路:栈模拟。
代码:
#include<bits/stdc++.h> using namespace std; int main(){ string ss; cin>>ss; int ans=0; stack<char> st; for(int i=0;i<ss.size();i++){ if(st.size()<=1){ st.push(ss[i]); } else { char x=ss[i]; char y=st.top(); st.pop(); char z=st.top(); st.pop(); if(x==y && y==z){ ans++; } else { st.push(z); st.push(y); st.push(x); } } } cout<<ans<<endl; }
H
I
思路:dfs序+扫描线
代码:
// #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 = 998244353; 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 = 3e5+9; int le[maxn],ri[maxn]; vector<int>mp[maxn]; int id[maxn], dfn[maxn], tim = 0, sz[maxn]; void dfs(int u) { dfn[u] = ++tim; id[tim] = u; sz[u] = 1; for(int v : mp[u]) { dfs(v); sz[u] += sz[v]; } } struct node{ int le, ri, id, op; node(int Le, int Ri, int Id, int Op){ le = Le; ri = Ri; id = Id; op = Op; } }; vector<node> g[maxn]; ll ans[maxn]; struct TT{ ll sum[maxn<<2], lazy[maxn<<2]; void pushdown(int le, int ri, int rt) { lazy[rt<<1] += lazy[rt]; lazy[rt<<1|1] += lazy[rt]; int mid = (le + ri) >> 1; sum[rt<<1] += 1ll*lazy[rt] * (mid - le + 1); sum[rt<<1|1] += 1ll*lazy[rt] * (ri - mid); lazy[rt] = 0; } void update(int L, int R, int c, int le, int ri, int rt) { if(le >= L && ri <= R) { sum[rt] += 1ll * c * (ri - le + 1); lazy[rt] += 1ll * c; return ; } int mid = (le + ri) >> 1; if(lazy[rt]) pushdown(le , ri, rt); if(L <= mid) update(L, R, c, le, mid, rt<<1); if(mid < R) update(L, R, c, mid+1, ri, rt<<1|1); sum[rt] = sum[rt<<1] + sum[rt<<1|1]; } ll query(int L, int R, int le, int ri, int rt) { if(le >= L && ri <= R) { return sum[rt]; } int mid = (le + ri) >> 1; if(lazy[rt]) pushdown(le, ri, rt); ll res = 0; if(L <= mid) res += query(L, R, le, mid, rt<<1); if(mid < R) res += query(L, R, mid+1, ri,rt<<1|1); return res; } } tree; int main(){ int n,m; scanf("%d%d", &n, &m); le[1] = 1, ri[1] = n; for(int i=1; i<=m; i++) { int u,v,l,r; scanf("%d%d%d%d", &u, &v, &l, &r); mp[u].pb(v); le[v] = l, ri[v] = r; } int N = m + 1; dfs(1); int q; scanf("%d", &q); for(int i=1; i<=q; i++) { int u, le, ri; scanf("%d%d%d", &u, &le, &ri); int t1 = dfn[u] - 1; g[t1].pb(node(le, ri, i, -1)); g[t1 + sz[u]].pb(node{le, ri, i, 1}); } for(int i=1; i<=tim; i++) { int u = id[i]; tree.update(le[u], ri[u], 1, 1, n, 1); for(node a : g[i]) { ans[a.id] += 1ll * a.op * tree.query(a.le, a.ri, 1, n, 1); } } for(int i=1; i<=q; i++) printf("%lld\n", ans[i]); return 0; }
J
队友补了
题号 | 标题 | 团队的状态 |
---|---|---|
A | The power of Fibonacci | 未通过 |
B | Quadratic equation | 通过 |
C | Inversions of all permutations | 未通过 |
D | Knapsack Cryptosystem | 通过 |
E | All men are brothers | 通过 |
F | Birthday Reminders | 未通过 |
G | Checkers | 未通过 |
H | Cutting Bamboos | 通过 |
I | KM and M | 未通过 |
J | Symmetrical Painting | 通过 |
A
B
思路:二次剩余
代码:
#include<bits/stdc++.h> #define ll long long using namespace std; const int p=1e9+7; int quick(int x,int n,int mod){ int ans=1; while(n){ if(n&1) ans=1ll*ans*x%mod; x=1ll*x*x%mod; n=n/2; } return ans; } int judge(int n,int p) {// p==2 直接 是n // x*x=n (mod p); (p是奇素数) int k=quick(n,(p-1)/2,p); if(k==0){ return 0; } // n==0; YES; if(k==1){ return 1; } // 1 ; YES; return -1; // -1 ; NO; } ll w; struct node{ ll x,y; }; node mul(node a,node b,ll p) { node ans={0,0}; ans.x=((a.x*b.x%p+a.y*b.y%p*w%p)%p+p)%p; ans.y=((a.x*b.y%p+a.y*b.x%p)%p+p)%p; return ans; } ll powwi(node a,ll b,ll p){ // pow node ans={1,0}; while(b){ if(b&1)ans=mul(ans,a,p); a=mul(a,a,p); b>>=1; } return ans.x%p; } ll slove(ll n,ll p){ n%=p; ll a; while(1){ a=rand()%p; w=((a*a%p-n)%p+p)%p; if(quick(w,(p-1)/2,p)==p-1)break; } node x={a,1}; return powwi(x,(p+1)/2,p); } int main(){ int T; scanf("%d",&T); while(T--){ ll b,c; scanf("%lld %lld",&b,&c); int x=((1ll*b*b-4*c)%p+p)%p; int flag=judge(x,p); ll aa,bb; if(flag==-1){ printf("-1 -1\n"); continue; } else if(flag==0){ aa=0; bb=p; } else { int cc=slove(x,p); aa=min(cc,p-cc); bb=max(cc,p-cc); } if( (b+aa)%2==1 && (b+bb)%2==1) { printf("-1 -1\n"); continue; } if( (b+aa)%2==0){ int x=(b+aa)/2;x=(x%p+p)%p; int xx=min(1ll*x,((b-x)%p+p)%p); int yy=max(1ll*x,((b-x)%p+p)%p); printf("%d %d\n",xx,yy); } else { int x=(b+bb)/2; x=(x%p+p)%p; int xx=min(1ll*x,((b-x)%p+p)%p); int yy=max(1ll*x,((b-x)%p+p)%p); printf("%d %d\n",xx,yy); } } }
C
D
思路:折半枚举
代码:
#include<bits/stdc++.h> #define ll long long #define ull unsigned long long using namespace std; const int maxn=100; map<ll,int> mp; ll a[maxn]; int main(){ int n; scanf("%d",&n); ll s; scanf("%lld",&s); for(int i=0;i<n;i++) scanf("%lld",&a[i]); if(n==1){ if(a[0]==s) printf("1"); else printf("0"); return 0; } int x=n/2; int y=n-x; int up=(1<<x); for(int i=0;i<up;i++){ ll temp=0; for(int j=0;j<x;j++){ if(i&(1<<j)){ temp+=a[j]; } } mp[temp]=i; } up=(1<<y); int ansx=0; int ansy=0; for(int i=0;i<up;i++){ ll temp=0; for(int j=0;j<y;j++){ if(i&(1<<j)){ temp+=a[j+x]; } } if(temp<=s && mp.find(s-temp)!=mp.end()){ ansx=mp[s-temp]; ansy=i; break; } } // cout<<ansx<<" "<<ansy<<endl; for(int i=0;i<x;i++){ if(ansx&(1ll<<i)){ printf("1"); }else { printf("0"); } } for(int i=0;i<y;i++){ if(ansy&(1ll<<i)){ printf("1"); }else { printf("0"); } } }
E
思路:考虑每加一条边对答案的贡献。
代码:
#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include<bits/stdc++.h> using namespace std; #define y1 y11 #define fi first #define se second #define pi acos(-1.0) #define LL long long //#define mp make_pair #define pb emplace_back #define ls rt<<1, l, m #define rs rt<<1|1, m+1, r #define ULL unsigned LL #define pll pair<LL, LL> #define pli pair<LL, int> #define pii pair<int, int> #define piii pair<pii, int> #define pdd pair<double, double> #define mem(a, b) memset(a, b, sizeof(a)) #define debug(x) cerr << #x << " = " << x << "\n"; #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); //head const int N = 1e5 + 5; int fa[N], n, m, x, y; LL sz[N]; int Find(int x) { if(x == fa[x]) return x; else return fa[x] = Find(fa[x]); } int main() { scanf("%d %d", &n, &m); for (int i = 1; i <= n; ++i) fa[i] = i, sz[i] = 1; LL d[4] = {n, n-1, n-2, n-3}; LL ans = 1; for (int i = 0; i < 4; ++i) if(d[i]%2 == 0) {d[i] /= 2; break;} for (int i = 0; i < 4; ++i) if(d[i]%2 == 0) {d[i] /= 2; break;} for (int i = 0; i < 4; ++i) if(d[i]%2 == 0) {d[i] /= 2; break;} for (int i = 0; i < 4; ++i) if(d[i]%3 == 0) {d[i] /= 3; break;} for (int i = 0; i < 4; ++i) ans = ans*d[i]; LL sum = n*1LL*(n-1)/2; for (int i = 1; i <= m; ++i) { printf("%lld\n", ans); scanf("%d %d", &x, &y); x = Find(x); y = Find(y); if(x == y) continue; sum -= sz[x]*1LL*(n-sz[x]); sum -= sz[y]*1LL*(n-sz[y]); sum += sz[x]*1LL*sz[y]; ans -= sz[x]*1LL*sz[y]*sum; sz[y] += sz[x]; sum += sz[y]*1LL*(n-sz[y]); fa[x] = y; } printf("%lld\n", ans); return 0; }
F
G
H
思路:二分+主席树
代码:
/* * @Author: chenkexing * @Date: 2019-08-14 21:32:30 * @Last Modified by: chenkexing * @Last Modified time: 2019-08-15 00:03:11 */ // #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 <unordered_map> // #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 unsigned long long ull; 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 N = 2e5 + 5, M = 4e6 + 5;//M为节点个数,为Q*log(N) int root[N], lson[M], rson[M], value[M], tot = 0; ll sum[M]; const double eps = 1e-7; //建树 void build(int &x, int l, int r) { x = ++tot; value[x] = 0; sum[x] = 0; if(l == r) { return ; } int m = (l+r) >> 1; build(lson[x], l, m); build(rson[x], m+1, r); value[x] = value[lson[x]] + value[rson[x]]; } // 将某个历史版本p位置的值加v void update(int old, int &x, int p, int v, int l, int r) { x = ++tot; lson[x] = lson[old], rson[x] = rson[old], value[x] = value[old] + v, sum[x] = sum[old] + p; if(l == r) return ; int m = (l+r) >> 1; if(p <= m) update(lson[x], lson[x], p, v, l, m); else update(rson[x], rson[x], p, v, m+1, r); } //访问某个历史版本L到R的区间和 int query(int L, int R, int x, int l, int r) { if(L <= l && r <= R) return value[x]; int m = (l+r) >> 1, ans = 0; if(L <= m) ans += query(L, R, lson[x], l, m); if(R > m) ans += query(L, R, rson[x], m+1, r); return ans; } ll query2(int L, int R, int x, int l, int r) { if(L <= l && r <= R) return sum[x]; int m = (l+r) >> 1; ll ans = 0; if(L <= m) ans += query2(L, R, lson[x], l, m); if(R > m) ans += query2(L, R, rson[x], m+1, r); return ans; } const int maxn = 2e5+9; ll pre[maxn], a[maxn]; double cal(double val, int L, int R) { int hi = floor(val); int cnt = query(0, hi, root[R], 0, 100000) - query(0, hi, root[L-1], 0, 100000); double ss = (R - L + 1 - cnt) * val; ss += 1.0*query2(0, hi,root[R], 0, 100000) - query2(0, hi, root[L-1], 0, 100000); return ss; } int main(){ int n,m; scanf("%d%d", &n, &m); build(root[0], 0, 100000); for(int i=1; i<=n; i++) { scanf("%lld", &a[i]), pre[i] = pre[i-1] + a[i]; update(root[i-1], root[i], a[i], 1, 0, 100000); } while(m--) { int L, R, x, y; scanf("%d%d%d%d", &L, &R, &x, &y); ll ss = pre[R] - pre[L-1]; double nd = ss*1.0 / y *(y - x); double le = 0, ri = 1000000005, res = 0; //debug(nd); while(le + eps < ri) { double mid = (le + ri) / 2; if(cal(mid, L, R) <= nd) le = mid, res = mid; else ri = mid; } printf("%.10f\n", res); } return 0; }
I
J
思路:差分
代码:
/* * @Author: chenkexing * @Date: 2019-08-16 15:34:14 * @Last Modified by: chenkexing * @Last Modified time: 2019-08-16 15:41:12 */ // #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 = 998244353; 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 = 300009; pii a[maxn * 3]; int main(){ int n; scanf("%d", &n); int tot = 0; for(int i=1; i<=n; i++) { int le,ri; scanf("%d%d", &le, &ri); a[++tot] = pii(2*le, 1); a[++tot] = pii(le + ri, -2); a[++tot] = pii(2*ri, 1); } sort(a+1, a+1+tot); ll ans = 0, sum = 0; ll cnt = a[1].se; for(int i=2; i<=tot; i++) { sum += cnt * (a[i].fi - a[i-1].fi); ans = max(ans, sum); cnt += a[i].se; } printf("%lld\n", ans); return 0; }
题号 | 标题 | 团队的状态 |
---|---|---|
A | Blackjack | 通过 |
B | Coffee Chicken | 通过 |
C | Gifted Composer | 未通过 |
D | Han Xin and His Troops | 通过 |
E | Hilbert Sort | 通过 |
F | Popping Balloons | 通过 |
G | Road Construction | 通过 |
H | Stammering Chemists | 通过 |
I | Travel Dream | 未通过 |
J | Wood Processing | 通过 |
A
队友补了
B
思路:递归
代码:
#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include<bits/stdc++.h> using namespace std; #define y1 y11 #define fi first #define se second #define pi acos(-1.0) #define LL long long //#define mp make_pair #define pb emplace_back #define ls rt<<1, l, m #define rs rt<<1|1, m+1, r #define ULL unsigned LL #define pll pair<LL, LL> #define pli pair<LL, int> #define pii pair<int, int> #define piii pair<pii, int> #define pdd pair<double, double> #define mem(a, b) memset(a, b, sizeof(a)) #define debug(x) cerr << #x << " = " << x << "\n"; #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); //head LL f[100] = {0, 6, 7}; //57 LL up = 2e12; int T, n; string s = "0COFFEE"; string t = "0CHICKEN"; LL k; void dfs(int x, LL L, LL R) { if(R > f[x]) R = f[x]; if(L > R) return ; if(x == 1) { for (int i = L; i <= R; ++i) putchar(s[i]); } else if(x == 2) { for (int i = L; i <= R; ++i) putchar(t[i]); } else { if(L > f[x-2]) { dfs(x-1, L-f[x-2], R-f[x-2]); } else if(R > f[x-2]) { dfs(x-2, L, f[x-2]); dfs(x-1, 1, R-f[x-2]); } else { dfs(x-2, L, R); } } } int main() { for (int i = 3; i < 100; ++i) { f[i] = f[i-1]+f[i-2]; if(f[i] > up) break; } scanf("%d", &T); while(T--) { scanf("%d %lld", &n, &k); if(n%2) dfs(min(57, n), k, k+9); else dfs(min(56, n), k, k+9); puts(""); } return 0; }
C
D
思路:大数写扩展中国剩余定理
代码:
import java.math.BigInteger; import java.util.*; public class Main { /** * @param args */ static BigInteger x; static BigInteger y; public static BigInteger exgcd(BigInteger a, BigInteger b) { if(b.compareTo(BigInteger.ZERO) == 0){ x = BigInteger.ONE; y = BigInteger.ZERO; return a; } BigInteger gcd = exgcd(b, a.remainder(b)); BigInteger t = x; x = y; y = t.subtract(a.divide(b).multiply(y)); return gcd; } public static void main(String[] args) { Scanner reader = new Scanner(System.in); int a[] = new int[105]; int b[] = new int[105]; int n = reader.nextInt(); BigInteger m = reader.nextBigInteger(); for (int i = 1; i <= n; ++i) { b[i] = reader.nextInt(); a[i] = reader.nextInt(); } BigInteger M = BigInteger.valueOf(b[1]), ans = BigInteger.valueOf(a[1]); boolean f = true; for (int i = 2; i <= n; ++i) { BigInteger A = M, B = BigInteger.valueOf(b[i]), C = (BigInteger.valueOf(a[i]).subtract(ans)).remainder(B); C = C.add(B).remainder(B); BigInteger gcd = exgcd(A, B), bg = B.divide(gcd); if(C.remainder(gcd).compareTo(BigInteger.ZERO) != 0) { f = false; break; } x = (x.multiply(C.divide(gcd))).remainder(bg); ans = ans.add(x.multiply(M)); M = M.multiply(bg); ans = ans.remainder(M); } ans = (ans.remainder(M).add(M)).remainder(M); if(f == false) System.out.println("he was definitely lying"); else if(ans.compareTo(m) > 0) System.out.println("he was probably lying"); else System.out.println(ans); } }
E
思路:递归
代码:
#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 <unordered_map> // #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 unsigned long long ull; 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 = 998244353; 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 = 1e6+9; pii a[maxn]; ll ksm(ll a, ll b) { ll res = 1; while(b > 0) { if(b & 1) res = res * a; a = a * a; b >>= 1; } return res; } vector<pii>ans; void dfs(int pt, int inv ,vector<pii>vec, int k, int xbase, int ybase){ if(vec.size() == 0) return; if(vec.size() == 1) { for(pii p : vec) ans.pb(p); return; } if(k == 0){ for(pii p : vec) ans.pb(p); return; } vector<pii>v[5]; int mid = ksm(2 , k-1); for(pii t : vec) { int x = t.fi, y = t.se; x -= xbase, y -= ybase; if(x <= mid && y <= mid) v[1].pb(t); else if(x > mid && y <= mid) v[2].pb(t); else if(x > mid && y > mid) v[3].pb(t); else v[4].pb(t); } if(pt == 1) { if(inv){ dfs(4, inv ^ 1, v[4], k-1, xbase, ybase + mid); dfs(1, inv, v[3], k-1, xbase+mid, ybase + mid); dfs(1, inv, v[2], k-1, xbase+mid, ybase); dfs(2, inv ^ 1, v[1], k-1,xbase, ybase); } else { dfs(2, inv ^ 1, v[1], k-1,xbase, ybase); dfs(1, inv, v[2], k-1,xbase+mid, ybase); dfs(1, inv, v[3], k-1,xbase+mid, ybase + mid); dfs(4, inv ^ 1, v[4], k-1, xbase, ybase + mid); } } else if(pt == 2){ if(inv) { dfs(1, inv ^ 1, v[1], k-1,xbase, ybase); dfs(2, inv, v[4], k-1, xbase, ybase + mid); dfs(2, inv, v[3], k-1,xbase+mid, ybase + mid); dfs(3, inv ^ 1, v[2], k-1,xbase+mid, ybase); } else { dfs(3, inv ^ 1, v[2], k-1,xbase+mid, ybase); dfs(2, inv, v[3], k-1,xbase+mid, ybase + mid); dfs(2, inv, v[4], k-1, xbase, ybase + mid); dfs(1, inv ^ 1, v[1], k-1,xbase, ybase); } } else if(pt == 3) { if(inv) { dfs(2, inv ^ 1, v[2], k-1,xbase+mid, ybase); dfs(3, inv, v[1], k-1,xbase, ybase); dfs(3, inv, v[4], k-1,xbase, ybase + mid); dfs(4, inv ^ 1, v[3], k-1,xbase+mid, ybase + mid); } else { dfs(4, inv ^ 1, v[3], k-1,xbase+mid, ybase + mid); dfs(3, inv, v[4], k-1, xbase, ybase + mid); dfs(3, inv, v[1], k-1,xbase, ybase); dfs(2, inv ^ 1, v[2], k-1,xbase+mid, ybase); } } else { if(inv) { dfs(3, inv ^ 1, v[3], k-1,xbase+mid, ybase + mid); dfs(4, inv, v[2], k-1,xbase+mid, ybase); dfs(4, inv, v[1], k-1,xbase, ybase); dfs(1, inv ^ 1, v[4], k-1, xbase, ybase + mid); } else { dfs(1, inv ^ 1, v[4], k-1, xbase, ybase + mid); dfs(4, inv, v[1], k-1,xbase, ybase); dfs(4, inv, v[2], k-1,xbase+mid, ybase); dfs(3, inv ^ 1, v[3], k-1,xbase+mid, ybase + mid); } } } int main(){ int n, k; scanf("%d%d", &n, &k); vector<pii>in; for(int i=1; i<=n; i++) { int x,y; scanf("%d%d", &x, &y); in.pb(pii(x, y)); } dfs(1, 0, in, k, 0, 0); for(pii p : ans) { printf("%d %d\n", p.fi, p.se); } return 0; }
F
思路:暴力+multiset
代码:
#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include<bits/stdc++.h> using namespace std; #define y1 y11 #define fi first #define se second #define pi acos(-1.0) #define LL long long //#define mp make_pair #define pb emplace_back #define ls rt<<1, l, m #define rs rt<<1|1, m+1, r #define ULL unsigned LL #define pll pair<LL, LL> #define pli pair<LL, int> #define pii pair<int, int> #define piii pair<pii, int> #define pdd pair<double, double> #define mem(a, b) memset(a, b, sizeof(a)) #define debug(x) cerr << #x << " = " << x << "\n"; #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); //head const int N = 1e5 + 1; multiset<int> s; vector<int> vc[N]; int n, x, y, r, cnt[N], tot[N]; int main() { scanf("%d %d", &n, &r); for (int i = 1; i <= n; ++i) { scanf("%d %d", &x, &y); vc[x].pb(y); cnt[y]++; } for (int i = 0; i < N; ++i) { tot[i] = cnt[i]; if(i+r < N) tot[i] += cnt[i+r]; if(i+r+r < N) tot[i] += cnt[i+r+r]; s.insert(tot[i]); } int ans = 0; for (int x = 0; x < N; ++x) { int tmp = vc[x].size(); if(x+r < N) tmp += vc[x+r].size(); if(x+r+r < N) tmp += vc[x+r+r].size(); for (int y : vc[x]) { if(y-r >= 0) { int t = tot[y-r]; s.erase(s.find(t)); s.insert(t-1); tot[y-r]--; } { int t = tot[y]; s.erase(s.find(t)); s.insert(t-1); tot[y]--; } if(y-2*r >= 0) { int t = tot[y-r-r]; s.erase(s.find(t)); s.insert(t-1); tot[y-r-r]--; } } if(x+r < N) for (int y : vc[x+r]) { if(y-r >= 0) { int t = tot[y-r]; s.erase(s.find(t)); s.insert(t-1); tot[y-r]--; } { int t = tot[y]; s.erase(s.find(t)); s.insert(t-1); tot[y]--; } if(y-2*r >= 0) { int t = tot[y-r-r]; s.erase(s.find(t)); s.insert(t-1); tot[y-r-r]--; } } if(x+r+r < N) for (int y : vc[x+r+r]) { if(y-r >= 0) { int t = tot[y-r]; s.erase(s.find(t)); s.insert(t-1); tot[y-r]--; } { int t = tot[y]; s.erase(s.find(t)); s.insert(t-1); tot[y]--; } if(y-2*r >= 0) { int t = tot[y-r-r]; s.erase(s.find(t)); s.insert(t-1); tot[y-r-r]--; } } tmp += *s.rbegin(); ans = max(ans, tmp); for (int y : vc[x]) { if(y-r >= 0) { int t = tot[y-r]; s.erase(s.find(t)); s.insert(t+1); tot[y-r]++; } { int t = tot[y]; s.erase(s.find(t)); s.insert(t+1); tot[y]++; } if(y-2*r >= 0) { int t = tot[y-r-r]; s.erase(s.find(t)); s.insert(t+1); tot[y-r-r]++; } } if(x+r < N) for (int y : vc[x+r]) { if(y-r >= 0) { int t = tot[y-r]; s.erase(s.find(t)); s.insert(t+1); tot[y-r]++; } { int t = tot[y]; s.erase(s.find(t)); s.insert(t+1); tot[y]++; } if(y-2*r >= 0) { int t = tot[y-r-r]; s.erase(s.find(t)); s.insert(t+1); tot[y-r-r]++; } } if(x+r+r < N) for (int y : vc[x+r+r]) { if(y-r >= 0) { int t = tot[y-r]; s.erase(s.find(t)); s.insert(t+1); tot[y-r]++; } { int t = tot[y]; s.erase(s.find(t)); s.insert(t+1); tot[y]++; } if(y-2*r >= 0) { int t = tot[y-r-r]; s.erase(s.find(t)); s.insert(t+1); tot[y-r-r]++; } } } printf("%d\n", ans); return 0; }
G
思路:对称轴一定平行或垂直与任意两点连线。
代码:
#include<bits/stdc++.h> using namespace std; #define pb emplace_back const double eps=1e-6; const int maxn=310; struct Point{ double x,y; double w; Point(){ x=0,y=0; } Point(double _x,double _y):x(_x),y(_y){} }; int n; Point pa[maxn]; bool up(Point a,Point b){ return a.w<b.w; } bool upx(Point a,Point b){ return a.x<b.x; } bool upy(Point a,Point b){ return a.y<b.y; } double k[maxn*maxn*2]; inline double dis(double b, double k) { return b/sqrt(k*k+1.0); } inline double solve(double l, double r, double k) { return dis(r-l, k)/2.0; } int main(){ cin >> n; for (int i = 1; i <= n; ++i) cin >> pa[i].x >> pa[i].y; int tot=0; double ans=0; for(int i=1;i<=n;i++){ for(int j=i+1;j<=n;j++){ if(fabs(pa[i].x-pa[j].x) < eps) continue; else if(fabs(pa[i].y-pa[j].y) < eps) continue; else { k[++tot]=(pa[j].y-pa[i].y)/(pa[j].x-pa[i].x); k[++tot] = -(pa[j].x-pa[i].x)/(pa[j].y-pa[i].y); } } } sort(pa+1,pa+1+n,upx); ans=max((pa[n/2+1].x-pa[n/2].x)/2,ans); sort(pa+1,pa+1+n,upy); ans=max((pa[n/2+1].y-pa[n/2].y)/2,ans); for (int i = 1; i <= tot; ++i) { for (int j = 1; j <= n; ++j) pa[j].w = pa[j].y-k[i]*pa[j].x; sort(pa+1, pa+1+n, up); ans = max(ans, solve(pa[n/2].w, pa[n/2+1].w, k[i])); } cout << fixed << setprecision(12) << ans <<endl; return 0; }
H
思路:水题
代码:
#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 <unordered_map> // #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 unsigned long long ull; 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 = 998244353; 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************/ int du[7], cnt[7]; pii a[7]; int main(){ int T; scanf("%d", &T); while(T--) { for(int i=1; i<=6; i++) du[i] = 0, cnt[i] = 0; for(int i=1; i<=5; i++) { int u,v; scanf("%d%d", &u, &v); du[u] ++; du[v]++; a[i].fi = u, a[i].se = v; } for(int i=1; i<=6; i++) cnt[du[i]]++; if(cnt[2] == 4) puts("n-hexane"); else if(cnt[4] == 1) puts("2,2-dimethylbutane"); else if(cnt[3] == 2) puts("2,3-dimethylbutane"); else { int cc1 = 0; for(int i=1; i<=5; i++) { int u = a[i].fi, v = a[i].se; if(du[u] == 3 && du[v] == 1) cc1++; if(du[v] == 3 && du[u] == 1) cc1++; } if(cc1 == 1) puts("3-methylpentane"); else puts("2-methylpentane"); } } return 0; }
I
J
思路:斜率优化dp,维护递增斜率$\frac{dp[j]-dp[k]+sum[k]-sum[j]+h[j+1]*sw[j]-h[k+1]*sw[k]}{h[j+1]-h[k+1]}$,其中$sum$是按高度排序后面积的前缀和,$sw$是宽度前缀和。
代码:
#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include<bits/stdc++.h> using namespace std; #define y1 y11 #define fi first #define se second #define pi acos(-1.0) #define LL long long //#define mp make_pair #define pb emplace_back #define ls rt<<1, l, m #define rs rt<<1|1, m+1, r #define ULL unsigned LL #define pll pair<LL, LL> #define pli pair<LL, int> #define pii pair<int, int> #define piii pair<pii, int> #define pdd pair<double, double> #define mem(a, b) memset(a, b, sizeof(a)) #define debug(x) cerr << #x << " = " << x << "\n"; #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); //head const int N = 5e3 + 10, M = 2e3 + 5; LL sum[N], sw[N], dp[M][N]; int h[N], w[N]; pii a[N]; int n, k; deque<int> q[M]; LL up(int p, int k, int j) { return dp[p][j]-dp[p][k]+sum[k]-sum[j]+h[j+1]*sw[j]-h[k+1]*sw[k]; } LL dw(int k, int j) { return h[j+1]-h[k+1]; } bool g(int p, int k, int j, LL C) { return up(p, k, j) <= C*1.0*dw(k, j); } bool gg(int p, int k, int j, int i) { return up(p, k, j)*1.0*dw(j, i) >= up(p, j, i)*1.0*dw(k, j); } int main() { scanf("%d %d", &n, &k); for (int i = 1; i <= n; ++i) scanf("%d %d", &a[i].se, &a[i].fi); sort(a+1, a+1+n); for (int i = 1; i <= n; ++i) h[i] = a[i].fi, w[i] = a[i].se, sw[i] = sw[i-1]+w[i], sum[i] = sum[i-1] + w[i]*1LL*h[i]; q[0].push_back(0); for (int i = 1; i <= n; ++i) { for (int j = min(k, i); j >= 1; --j) { while(q[j-1].size() >= 2) { int a = q[j-1].front(); q[j-1].pop_front(); int b = q[j-1].front(); if(g(j-1, a, b, sw[i])) ; else { q[j-1].push_front(a); break; } } if(!q[j-1].empty()) { int x = q[j-1].front(); dp[j][i] = dp[j-1][x] + sum[i]-sum[x]-h[x+1]*(sw[i]-sw[x]); while(q[j].size() >= 2) { int b = q[j].back(); q[j].pop_back(); int a = q[j].back(); if(gg(j, a, b, i)) ; else { q[j].push_back(b); break; } } q[j].push_back(i); } } } printf("%lld\n", dp[k][n]); return 0; }
杭电
2019 Multi-University Training Contest 1
Solved | Pro.ID | Title |
1001 | Blank | |
1002 | Operation | |
1003 | Milk | |
1004 | Vacation | |
1005 | Path | |
1006 | Typewriter | |
1007 | Meteor | |
1008 | Desert | |
1009 | String | |
1010 | Kingdom | |
1011 | Function | |
1012 | Sequence | |
1013 | Code |
1001
思路:dp
$dp[i][j][k][l]$表示每种颜色出现位置分别为$i$,$j$,$k$,$l$,$i \le j \le k \le l$,其中,等号只有在等于0时才取得到。
不必在意每种颜色在哪个位置,只需要知道这四个位置的颜色都是不同的。然后考虑转移到,有如下四种状态可以转移到:
$dp[j][k][l][l+1]$,$dp[i][k][l][l+1]$,$dp[i][j][l][l+1]$,$dp[i][j][k][l+1]$,然后第四个维度滚动数组优化一下
于是时间复杂度$O(C(n, 4))$,空间复杂度$O(n^3)$
代码:
#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include<bits/stdc++.h> using namespace std; #define y1 y11 #define fi first #define se second #define pi acos(-1.0) #define LL long long //#define mp make_pair #define pb emplace_back #define ls rt<<1, l, m #define rs rt<<1|1, m+1, r #define ULL unsigned LL #define pll pair<LL, LL> #define pli pair<LL, int> #define pii pair<int, int> #define piii pair<pii, int> #define pdd pair<double, double> #define mem(a, b) memset(a, b, sizeof(a)) #define debug(x) cerr << #x << " = " << x << "\n"; #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); //head const int N = 103; const int MOD = 998244353; int dp[N][N][N][2], n, m, l, r, x, T; vector<int> vc[N][5]; int main() { scanf("%d", &T); while(T--) { scanf("%d %d", &n, &m); for (int i = 1; i <= n; ++i) for (int j = 1; j <= 4; ++j) vc[i][j].clear(); for (int i = 1; i <= m; ++i) scanf("%d %d %d", &l, &r, &x), vc[r][x].pb(l); dp[0][0][0][0] = 1; int now = 0, ans = 0; for (int l = 0; l <= n; ++l) { now ^= 1; for (int i = 0; i <= l+1; ++i) for (int j = i; j <= l+1; ++j) for (int k = j; k <= l+1; ++k) dp[i][j][k][now] = 0; for (int k = l; k >= 0; --k) { bool f = false; for (int x : vc[l][1]) { if(x <= k) { f = true; break; } } if(f) continue; f = false; for (int x : vc[l][2]) { if(x > k) { f = true; break; } } if(f) break; for (int j = k; j >= 0; --j) { bool f = false; for (int x : vc[l][2]) { if(x <= j) { f = true; break; } } if(f) continue; f = false; for (int x : vc[l][3]) { if(x > j) { f = true; break; } } if(f) break; for (int i = j; i >= 0; --i) { bool f = false; for (int x : vc[l][3]) { if(x <= i) { f = true; break; } } if(f) continue; f = false; for (int x : vc[l][4]) { if(x > i) { f = true; break; } } if(f) break; //cout << i << " " << j << " " << k << " " << l << endl; if(l != n) { (dp[j][k][l][now] += dp[i][j][k][now^1]) %= MOD; (dp[i][k][l][now] += dp[i][j][k][now^1]) %= MOD; (dp[i][j][l][now] += dp[i][j][k][now^1]) %= MOD; (dp[i][j][k][now] += dp[i][j][k][now^1]) %= MOD; } else { (ans += dp[i][j][k][now^1]) %= MOD; } } } } } printf("%d\n", ans); } return 0; }
1002
思路:线性基+贪心,cf原题,详见FCY博客
代码:
using namespace std; #define y1 y11 #define fi first #define se second #define pi acos(-1.0) #define LL long long //#define mp make_pair #define pb emplace_back #define ls rt<<1, l, m #define rs rt<<1|1, m+1, r #define ULL unsigned LL #define pll pair<LL, LL> #define pli pair<LL, int> #define pii pair<int, int> #define piii pair<pii, int> #define pdd pair<double, double> #define mem(a, b) memset(a, b, sizeof(a)) #define debug(x) cerr << #x << " = " << x << "\n"; #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); //head const int N = 1e6 + 3; int a[N], base[N][30], pos[N][30]; inline void add(int p) { int x = a[p]; int pp = p; for (int i = 29; i >= 0; --i) base[p][i] = base[p-1][i], pos[p][i] = pos[p-1][i]; for (int i = 29; i >= 0; --i) { if(x&(1<<i)) { if(!base[pp][i]) { base[pp][i] = x; pos[pp][i] = p; return ; } if(p > pos[pp][i]) swap(base[pp][i], x), swap(pos[pp][i], p); x ^= base[pp][i]; } } } inline int solve(int L, int R) { int res = 0; for (int i = 29; i >= 0; --i) { if(base[R][i] && pos[R][i] >= L) { if((base[R][i]^res) > res) res ^= base[R][i]; } } return res; } int T, n, m, op, l, r; int main() { scanf("%d", &T); while(T--) { scanf("%d %d", &n, &m); for (int i = 1; i <= n; ++i) scanf("%d", &a[i]), add(i); int ans = 0; for (int i = 1; i <= m; ++i) { scanf("%d", &op); if(op == 0) { scanf("%d %d", &l, &r); l = (l^ans)%n+1; r = (r^ans)%n+1; if(l > r) swap(l, r); ans = solve(l, r); printf("%d\n", ans); } else { scanf("%d", &l); l ^= ans; a[++n] = l; add(n); } } } return 0; } /* 8 8 8 1 2 3 4 5 6 7 8 */
1003
1004
思路:贪心,假设每辆车都跑到最前面,时间取最大值
代码:
#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include<bits/stdc++.h> using namespace std; #define y1 y11 #define fi first #define se second #define pi acos(-1.0) #define LL long long //#define mp make_pair #define pb emplace_back #define ls rt<<1, l, m #define rs rt<<1|1, m+1, r #define ULL unsigned LL #define pll pair<LL, LL> #define pli pair<LL, int> #define pii pair<int, int> #define piii pair<pii, int> #define pdd pair<double, double> #define mem(a, b) memset(a, b, sizeof(a)) #define debug(x) cerr << #x << " = " << x << "\n"; #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); //head const int N = 1e5 + 3; int l[N]; int s[N]; int v[N]; LL ll[N]; int main(){ int n; while(~scanf("%d",&n)){ for(int i=0;i<=n;i++) scanf("%d",&l[i]); for(int i=0;i<=n;i++) scanf("%d",&s[i]); for(int i=0;i<=n;i++) scanf("%d",&v[i]); for(int i=1;i<=n;i++){ ll[i]=ll[i-1]+l[i]; } double ans=0; for(int i=n;i>=0;i--){ ans=max(ans,(ll[i]+s[i])*1.0/v[i]); } printf("%.10f\n",ans); } }
1005
思路:先建出从1出发的dijkstra图,然后在这张图上跑1到n的最小割。
代码:
#include <bits/stdc++.h> 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; template<class T> void _R(T &x) { cin >> x; } void _R(int &x) { scanf("%d", &x); } void _R(ll &x) { scanf("%lld", &x); } void _R(double &x) { scanf("%lf", &x); } void _R(char &x) { scanf(" %c", &x); } void _R(char *x) { scanf("%s", x); } void R() {} template<class T, class... U> void R(T &head, U &... tail) { _R(head); R(tail...); } 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; } const int inf = 0x3f3f3f3f; const ll inff = 0x3f3f3f3f3f3f3f3f; const int mod = 1e9+7; /**********showtime************/ const int maxn = 10009; vector<pii>mp[maxn]; ll dis[maxn]; int n,m; void dji(int s) { priority_queue<pll>que; que.push(pll(0, s)); for(int i=1; i<=n; i++) { dis[i] = inff; } dis[s] = 0; while(!que.empty()) { pll t = que.top(); que.pop(); int u = t.se; if(dis[u] < -1ll*t.fi) continue; for(int i=0; i<mp[u].size(); i++) { int v = mp[u][i].fi; int w = mp[u][i].se; if(dis[v] > dis[u] + w) { dis[v] = dis[u] + w; que.push(pll(-1ll*dis[v], v)); } } } } struct E{ int v; ll w; int nxt; }edge[20009]; int head[maxn], gtot = 0; void addedge(int u, int v, ll w) { edge[gtot].v = v; edge[gtot].w = w; edge[gtot].nxt = head[u]; head[u] = gtot++; edge[gtot].v = u; edge[gtot].w = 0; edge[gtot].nxt = head[v]; head[v] = gtot++; } int dd[maxn], cur[maxn]; bool bfs(int s, int t) { for(int i=s; i<=t; i++) cur[i] = head[i], dd[i] = inf; queue<int>que; que.push(s); dd[s] = 0; while(!que.empty()) { int u = que.front(); que.pop(); for(int i=head[u]; ~i; i=edge[i].nxt) { int v = edge[i].v;ll w = edge[i].w; if(w > 0 && dd[v] > dd[u] + 1) { dd[v] = dd[u] + 1; que.push(v); } } } return dd[t] < inf; } ll dfs(int u, int t, ll maxflow) { if(u == t || maxflow == 0) return maxflow; for(int i=cur[u]; ~i; i=edge[i].nxt) { cur[u] = i; int v = edge[i].v; ll w = edge[i].w; if(dd[v] == dd[u] + 1 && w > 0) { ll f = dfs(v, t, min(maxflow, 1ll*w)); if(f > 0) { edge[i].w -= f; edge[i ^ 1].w += f; return f; } } } return 0; } ll dinic(int s, int t){ ll flow = 0; while(bfs(s, t)) { while(ll f = dfs(s, t, inff)) flow += f; } return flow; } int main(){ int T; scanf("%d", &T); while(T--) { scanf("%d%d", &n, &m); gtot = 0; for(int i=1; i<=n; i++) mp[i].clear(), head[i] = -1; for(int i=1; i<=m; i++) { int u,v,c; scanf("%d%d%d", &u, &v, &c); mp[u].pb(pii(v, c)); } dji(1); for(int i=1; i<=n; i++) { int u = i; for(pii p : mp[i]) { int v = p.fi, w = p.se; if(dis[v] == dis[u] + w){ addedge(u, v, w); } } } printf("%lld\n", dinic(1, n)); } return 0; }
1006
队友补了
1007
1008
1009
思路:贪心,每次在能选的字符中选个最小的。用队列记录每个字符的位置,并预处理好每个位置后面每个字符的个数。有很一些限制条件,写起来不简单。
代码:
#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include<bits/stdc++.h> using namespace std; #define y1 y11 #define fi first #define se second #define pi acos(-1.0) #define LL long long //#define mp make_pair #define pb emplace_back #define ls rt<<1, l, m #define rs rt<<1|1, m+1, r #define ULL unsigned LL #define pll pair<LL, LL> #define pli pair<LL, int> #define pii pair<int, int> #define piii pair<pii, int> #define pdd pair<double, double> #define mem(a, b) memset(a, b, sizeof(a)) #define debug(x) cerr << #x << " = " << x << "\n"; #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); //head const int N = 1e5 + 5; char s[N]; queue<int> q[26]; int L[26], R[26], dp[N][26], n, k; vector<int> vc; int main() { while(~scanf("%s %d", s+1, &k)) { int n = strlen(s+1); for (int i = 0; i < 26; ++i) scanf("%d %d", &L[i], &R[i]); for (int i = 0; i < 26; ++i) dp[n+1][i] = 0; for (int i = n; i >= 1; --i) { for (int j = 0; j < 26; ++j) dp[i][j] = dp[i+1][j]; dp[i][s[i]-\'a\']++; } for (int i = 0; i < 26; ++i) while(!q[i].empty()) q[i].pop(); for (int i = 1; i <= n; ++i) q[s[i]-\'a\'].push(i); vc.clear(); int tot = 0; for (int i = 0; i < 26; ++i) tot += L[i]; while(true) { if(vc.size() == k) break; bool f = false; for (int i = 0; i < 26; ++i) { if(!q[i].empty() && R[i] > 0 && tot-L[i] <= k-vc.size()-1) { //cout << i <<endl; bool ff = false; int CC = 0; for (int j = 0; j < 26; ++j) { if(dp[q[i].front()][j] < L[j]) ff = true; CC += min(R[j], dp[q[i].front()][j]); } if(ff) continue; if(CC < k-vc.size()) continue; vc.pb(q[i].front()); q[i].pop(); f = true; if(L[i]) { L[i]--; tot--; } if(R[i]) R[i]--; break; } } if(!f) break; if(!vc.empty()) for (int i = 0; i < 26; ++i) { while(!q[i].empty() && q[i].front() < vc.back()) q[i].pop(); } } if(vc.size() != k) printf("-1\n"); else { for (int x : vc) putchar(s[x]); puts(""); } } return 0; } /* ababababab 10 5 5 5 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 */
1010
1011
队友补了
1012
思路:母函数+NTT
代码:
#include<bits/stdc++.h> using namespace std; #define LL long long const int N = 400100, P = 998244353; const int M = 1.2e6; inline int qpow(int x, int y) { int res(1); while (y) { if (y & 1) res = 1ll * res * x % P; x = 1ll * x * x % P; y >>= 1; } return res; } int r[N]; void ntt(int *x, int n, int opt) { register int i, j, k, m, gn, g, tmp; for (i = 0; i < n; ++i) if (r[i] < i) swap(x[i], x[r[i]]); for (m = 2; m <= n; m <<= 1) { k = m >> 1; gn = qpow(3, (P - 1) / m); ///3是原根 for (i = 0; i < n; i += m) { g = 1; for (j = 0; j < k; ++j, g = 1ll * g * gn % P) { tmp = 1ll * x[i + j + k] * g % P; x[i + j + k] = (x[i + j] - tmp + P) % P; x[i + j] = (x[i + j] + tmp) % P; } } } if (opt == -1) { reverse(x + 1, x + n); register int inv = qpow(n, P - 2); for (i = 0; i < n; ++i) x[i] = 1ll * x[i] * inv % P; } } int A[N], B[N], C[N], f[M], invf[M], a[N]; int T, nm, q, x, y, z, c; inline void init() { f[0] = 1; for (int i = 1; i < M; ++i) f[i] = (f[i-1]*1LL*i)%P; invf[M-1] = qpow(f[M-1], P-2); for (int i = M-2; i >= 0; --i) invf[i] = invf[i+1]*1LL*(i+1)%P; } inline int CC(int n, int m) { if(m < 0 || m > n) return 0; return (f[n]*1LL*invf[m]%P*1LL*invf[n-m])%P; } int main() { init(); scanf("%d", &T); while(T--){ int n, m, L = 0; x = y = z = 0; scanf("%d %d", &nm, &q); for (int i = 0; i < nm; ++i) scanf("%d", &a[i]); for (int i = 0; i < q; ++i) { scanf("%d", &c); if(c == 1) x++; else if(c == 2) y++; else z++; } L = 0; n = m = nm; m = n+m; for(n = 1; n <= m; n <<= 1) L++; for (int i = 0; i < n; i++) r[i] = (r[i>>1]>>1) | ((i&1) << L-1); if(x) { for (int i = 0; i < nm; ++i) A[i] = a[i]; for (int i = 0; i < nm; ++i) B[i] = CC(i+x-1, i); ntt(A, n, 1); ntt(B, n, 1); for (int i = 0; i < n; ++i) C[i] = 1ll * A[i] * B[i] % P; ntt(C, n, -1); for (int i = 0; i < nm; ++i) a[i] = C[i]; for (int i = 0; i < n; ++i) A[i] = B[i] = C[i] = 0; } if(y) { for (int i = 0; i < nm; ++i) A[i] = a[i]; for (int i = 0; 2*i < nm; ++i) B[2*i] = CC(i+y-1, i); ntt(A, n, 1); ntt(B, n, 1); for (int i = 0; i < n; ++i) C[i] = 1ll * A[i] * B[i] % P; ntt(C, n, -1); for (int i = 0; i < nm; ++i) a[i] = C[i]; for (int i = 0; i < n; ++i) A[i] = B[i] = C[i] = 0; } if(z) { for (int i = 0; i < nm; ++i) A[i] = a[i]; for (int i = 0; 3*i < nm; ++i) B[3*i] = CC(i+z-1, i); ntt(A, n, 1); ntt(B, n, 1); for (int i = 0; i < n; ++i) C[i] = 1ll * A[i] * B[i] % P; ntt(C, n, -1); for (int i = 0; i < nm; ++i) a[i] = C[i]; for (int i = 0; i < n; ++i) A[i] = B[i] = C[i] = 0; } LL ans = 0; for (int i = 0; i < nm; ++i) ans ^= ((i+1)*1LL*a[i]); printf("%lld\n", ans); } return 0; }
1013
思路:假设要求的三个变量为$(b,w1,w2)$。首先很容易想到$b$只是做一个平移运动,只要原来应该大于0的元素的最小值大于应该小于0的元素的最大值,
就一定可以找到一个$b$平移所有元素使得大于0的元素大于0,小于0的小于0。所以$b$完全可以忽略。那么就只有两个变量$w1$,$w2$需要确定。根据上面
的结论,我们要找到$w1$,$w2$,使得应该大于0的元素的相对大小大于小于0的。即对于任意$i$,$j$,如果$y_i == 1 且 y_j == -1$,那么要保证
$w1*x1_i +w2*x2_i > w1*x1_j +w2*x2_j$ 。两边同除以$w1$,$x1_i +\frac{w2}{w1}*x2_i > x1_j +\frac{w2}{w1}*x2_j$ ,所以只要确定一个变量$\frac{w2}{w1}$
就可以啦,于是$n^2$枚举,判断这个变量的存不存在一个可行区间就可以啦。如果$w1==0$怎么办,那么假设它等于0再判断一遍,我没有判也过了。
还有一点,由于$w1$的正负性不确定,所以$x1_i$的系数不一定是1,可能还是-1,两个都要判一遍。
代码:
#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include<bits/stdc++.h> using namespace std; #define y1 y11 #define fi first #define se second #define pi acos(-1.0) #define LL long long //#define mp make_pair #define pb emplace_back #define ls rt<<1, l, m #define rs rt<<1|1, m+1, r #define ULL unsigned LL #define pll pair<LL, LL> #define pli pair<LL, int> #define pii pair<int, int> #define piii pair<pii, int> #define pdd pair<double, double> #define mem(a, b) memset(a, b, sizeof(a)) #define debug(x) cerr << #x << " = " << x << "\n"; #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); //head const int N = 105; const double INF = 1LL<<60; int T, n; int x1[N], x2[N], y[N]; int main() { scanf("%d", &T); while(T--) { scanf("%d", &n); for (int i = 1; i <= n; ++i) scanf("%d %d %d", &x1[i], &x2[i], &y[i]); double L = -(1LL<<60), R =1LL<<60; for (int i = 1; i <= n; ++i) { for (int j = 1; j <= n; ++j) { if(i == j) continue; if(y[i] == 1 && y[j] == -1) { if(x2[i] == x2[j]) continue; double d = x2[j]-x2[i]; double up = x1[i]-x1[j]; if(d < 0) L = max(L, up/d); else R = min(R, up/d); } } } if(L <= R) { printf("Successful!\n"); continue; } L = -(1LL<<60), R =1LL<<60; for (int i = 1; i <= n; ++i) { for (int j = 1; j <= n; ++j) { if(i == j) continue; if(y[i] == 1 && y[j] == -1) { if(x2[i] == x2[j]) continue; double d = x2[j]-x2[i]; double up = -x1[i]+x1[j]; if(d < 0) L = max(L, up/d); else R = min(R, up/d); } } } if(L <= R) { printf("Successful!\n"); continue; } printf("Infinite loop!\n"); } return 0; }
2019 Multi-University Training Contest 2
Solved | Pro.ID | Title |
1001 | Another Chess Problem | |
1002 | Beauty Of Unimodal Sequence | |
1003 | Coefficient | |
1004 | Double Tree | |
1005 | Everything Is Generated In Equal Probability | |
1006 | Fantastic Magic Cube | |
1007 | Game | |
1008 | Harmonious Army | |
1009 | I Love Palindrome String | |
1010 | Just Skip The Problem | |
1011 | Keen On Everything But Triangle | |
1012 | Longest Subarray |
1001
1002
1003
1004
1005
思路:打表找规律
代码:
#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include<bits/stdc++.h> using namespace std; #define y1 y11 #define fi first #define se second #define pi acos(-1.0) #define LL long long //#define mp make_pair #define pb emplace_back #define ls rt<<1, l, m #define rs rt<<1|1, m+1, r #define ULL unsigned LL #define pll pair<LL, LL> #define pli pair<LL, int> #define pii pair<int, int> #define piii pair<pii, int> #define pdd pair<double, double> #define mem(a, b) memset(a, b, sizeof(a)) #define debug(x) cerr << #x << " = " << x << "\n"; #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); //head const int MOD = 998244353; const int N = 3e3 + 10; LL t[N], s[N]; LL q_pow(LL n, LL k) { LL res = 1; while(k) { if(k&1) res = (res*n)%MOD; n = (n*n)%MOD; k >>= 1; } return res; } int n; int main() { t[1] = 0; LL now = 2; for (int i = 2; i < N; ++i) { t[i] = (t[i-1]+now)%MOD; now = (now+2)%MOD; } for (int i = 1; i < N; ++i) s[i] =(s[i-1]+t[i])%MOD; while(~scanf("%d", &n)) { printf("%lld\n", s[n]*q_pow(3*n, MOD-2)%MOD); } return 0; }
1006
1007
1008
队友补了
1009
思路:回文自动机,在回文树上dfs,跑一个前缀的正反hash值,然后就可以判断每一个本质不同的回文串的一半是不是也是回文串。
队友代码:
#include<bits/stdc++.h> #define ll long long #define LL long long using namespace std; const int maxn=3e5+10; const int mod=1e9+7; const int h1=222333; char ss[maxn]; int a[maxn]; int ha[maxn]; int hb[maxn]; int hh[maxn]; struct PAM{ #define ll long long #define LL long long static const int maxn=3e5+10; static const int num=27; int fail[maxn],cnt[maxn],len[maxn],ch[maxn][num]; int last,tot; LL ans; void inint(){ last=0; tot=0; fail[0]=fail[1]=1; len[0]=0; len[1]=-1; tot++; } int get_fail(int p,int pos){ while(ss[pos-len[p]-1]!=ss[pos]) p=fail[p]; return p; } void add(int x,int pos){ int p=get_fail(last,pos); if(!ch[p][x]){ len[++tot]=len[p]+2; fail[tot]=ch[get_fail(fail[p],pos)][x]; ch[p][x]=tot; ans++; } cnt[last=ch[p][x]]++; } void count(){ // bu zhi bu tong hui wen ge shu for(int i=tot;i>=0;i--){ cnt[fail[i]]+=cnt[i]; } } void dfs(int x,int pos){ for(int i=0;i<num;i++){ if(ch[x][i]){ if(pos==0) ha[pos]=(1ll*i)%mod; else ha[pos]=(1ll*ha[pos-1]*h1+i)%mod; if(pos==0) hb[pos]=(1ll*i*hh[pos])%mod; else hb[pos]=(1ll*i*hh[pos]+hb[pos-1])%mod; int k=ch[x][i]; if(ha[pos]==hb[pos]){ a[len[k]]+=cnt[k]; } dfs(k,pos+1); } } } void work(){ dfs(0,0); dfs(1,0); } void clear(){ for(int i=0;i<=tot;i++){ fail[i]=0; len[i]=0; cnt[i]=0; for(int j=0;j<num;j++) ch[i][j]=0; } last=tot=ans=0; } }pam; int main(){ hh[0]=1; for(int i=1;i<maxn;i++) hh[i]=1ll*hh[i-1]*h1%mod; while(~scanf("%s",ss)){ int l=strlen(ss); pam.inint(); //cout<<l<<endl; for(int i=0;i<l;i++) pam.add(ss[i]-\'a\',i); pam.count(); pam.work(); for(int i=1;i<=l;i++){ if(i!=1) printf(" "); printf("%d",a[i]); a[i]=0; }printf("\n"); pam.clear(); } }
1010
思路:$n!$,当$n>=mod$时,等于$0$
代码:
#include <iostream> #include <vector> #include <queue> #include <algorithm> 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; template<class T> void _R(T &x) { cin >> x; } void _R(int &x) { scanf("%d", &x); } void _R(ll &x) { scanf("%lld", &x); } void _R(double &x) { scanf("%lf", &x); } void _R(char &x) { scanf(" %c", &x); } void _R(char *x) { scanf("%s", x); } void R() {} template<class T, class... U> void R(T &head, U &... tail) { _R(head); R(tail...); } 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; } const int inf = 0x3f3f3f3f; const ll inff = 0x3f3f3f3f3f3f3f3f; const int mod = 1e6+3; /**********showtime************/ const int maxn = 1e6+5; ll fac[maxn]; int main(){ int n; fac[0] = 1; for(int i=1; i<maxn; i++) { fac[i] = fac[i-1] * i % mod; } while(~scanf("%d", &n)) { if(n >= mod) puts("0"); else { printf("%lld\n", fac[n]); } } return 0; }
1011
思路:主席树找区间第$k$大
代码:
#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include<bits/stdc++.h> using namespace std; #define fi first #define se second #define pi acos(-1.0) #define LL long long //#define mp make_pair #define pb push_back #define ls rt<<1, l, m #define rs rt<<1|1, m+1, r #define ULL unsigned LL #define pll pair<LL, LL> #define pii pair<int, int> #define piii pair<pii, int> #define mem(a, b) memset(a, b, sizeof(a)) #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); #define fopen freopen("in.txt", "r", stdin);freopen("out.txt", "w", stout); //head const int N = 1e5 + 5, M = 5e6 + 5;//M为节点个数,为Q*log(N) int root[N], lson[M], rson[M], value[M], tot = 0; int a[N], v[N]; vector<int>vc; int n, m, l, r, k, q; void build(int &x, int l, int r) { x = ++tot; if(l == r) { value[x] = 0; return ; } int m = (l+r) >> 1; build(lson[x], l, m); build(rson[x], m+1, r); value[x] = value[lson[x]] + value[rson[x]]; } void update(int old, int &x, int p, int v, int l, int r) { x = ++tot; lson[x] = lson[old], rson[x] = rson[old], value[x] = value[old] + v; if(l == r) return ; int m = (l+r) >> 1; if(p <= m) update(lson[x], lson[x], p, v, l, m); else update(rson[x], rson[x], p, v, m+1, r); } int query(int x, int y, int l, int r, int k) { if(l == r) return l; int m = (l+r) >> 1, cnt = value[lson[y]] - value[lson[x]]; if(k <= cnt) return query(lson[x], lson[y], l, m, k); else return query(rson[x], rson[y], m+1, r, k-cnt); } int main() { while(~scanf("%d %d", &n, &m)) { vc.clear(); for (int i = 1; i <= n; i++) scanf("%d", &a[i]), vc.pb(a[i]); sort(vc.begin(), vc.end()); vc.erase(unique(vc.begin(), vc.end()), vc.end()); for (int i = 1; i <= n; i++) { int id = lower_bound(vc.begin(), vc.end(), a[i]) - vc.begin() + 1; v[id] = a[i]; a[i] = id; } tot = 0; build(root[0], 1, n); for (int i = 1; i <= n; i++) update(root[i-1], root[i], a[i], 1, 1, n); while(m--) { scanf("%d %d", &l, &r); vector<int> t; if(r-l+1 > 50) { int up = 45; for (int k = 1; k <= up; ++k) t.pb(v[query(root[l-1], root[r], 1, n, (r-l+1-k+1))]); } else { for (int k = l; k <= r; ++k) t.pb(v[a[k]]); sort(t.begin(), t.end(), greater<int>()); } LL ans = -1; //cout << t.size() << endl; for (int i = 0; i+2 < t.size(); ++i) { if(t[i+1]+t[i+2] > t[i]) { ans = 1LL*t[i]+1LL*t[i+1]+1LL*t[i+2]; break; } } printf("%lld\n", ans); } } return 0; }
1012
思路:考虑到固定一个右端点,对于每种颜色,可行的区间是两段区间(一段包含至少$k$个,一段一个都不包含),那么我们用线段树维护这些区间,
最后找第一个被$c$种颜色覆盖的位置。
代码:
#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include<bits/stdc++.h> using namespace std; #define y1 y11 #define fi first #define se second #define pi acos(-1.0) #define LL long long //#define mp make_pair #define pb emplace_back #define ls rt<<1, l, m #define rs rt<<1|1, m+1, r #define ULL unsigned LL #define pll pair<LL, LL> #define pli pair<LL, int> #define pii pair<int, int> #define piii pair<pii, int> #define pdd pair<double, double> #define mem(a, b) memset(a, b, sizeof(a)) #define debug(x) cerr << #x << " = " << x << "\n"; #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); //head const int N = 1e5 + 5; int n, c, k, a[N]; vector<int> vc[N]; struct Node { int v, lz; }tree[N<<2]; inline void push_up(int rt) { tree[rt].v = max(tree[rt<<1].v, tree[rt<<1|1].v); } inline void push_down(int rt) { tree[rt<<1].v += tree[rt].lz; tree[rt<<1].lz += tree[rt].lz; tree[rt<<1|1].v += tree[rt].lz; tree[rt<<1|1].lz += tree[rt].lz; tree[rt].lz = 0; } void build(int rt, int l, int r) { tree[rt].lz = 0; if(l == r) { tree[rt].v = c; return ; } int m = l+r >> 1; build(ls); build(rs); push_up(rt); } void update(int L, int R, int x, int rt, int l, int r) { if(L <= l && r <= R) { tree[rt].v += x; tree[rt].lz += x; return ; } if(tree[rt].lz) push_down(rt); int m = l+r >> 1; if(L <= m) update(L, R, x, ls); if(R > m) update(L, R, x, rs); push_up(rt); } int query(int x, int rt, int l, int r) { if(l == r) return l; int m = l+r >> 1; if(tree[rt].lz) push_down(rt); if(tree[rt<<1].v == x) return query(x, ls); else if(tree[rt<<1|1].v == x) return query(x, rs); else return -1; } int main() { while(~scanf("%d %d %d", &n, &c, &k)) { for (int i = 1; i <= n; ++i) scanf("%d", &a[i]); for (int i = 1; i <= c; ++i) vc[i].clear(); build(1, 1, n); int ans = 0; for (int i = 1; i <= n; ++i) { vc[a[i]].pb(i); update(vc[a[i]].size() == 1?1:(vc[a[i]][vc[a[i]].size()-2]+1), vc[a[i]].back(), -1, 1, 1, n); if(vc[a[i]].size() >= k) update(vc[a[i]].size() == k?1:(vc[a[i]][vc[a[i]].size()-k-1]+1), vc[a[i]][vc[a[i]].size()-k], 1, 1, 1, n); int p = query(c, 1, 1, n); if(~p)ans = max(ans, i-p+1); } printf("%d\n", ans); } return 0; }
2019 Multi-University Training Contest 3
Solved | Pro.ID | Title |
1001 | Azshara\'s deep sea | |
1002 | Blow up the city | |
1003 | Yukikaze and Demons | |
1004 | Distribution of books | |
1005 | Easy Math Problem | |
1006 | Fansblog | |
1007 | Find the answer | |
1008 | Game | |
1009 | K Subsequence | |
1010 | Sindar\'s Art Exhibition | |
1011 | Squrirrel |
1001
1002
思路:建反向图,然后就是求DAG的从入度为0出发的支配树。
代码:
#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include<bits/stdc++.h> using namespace std; #define y1 y11 #define fi first #define se second #define pi acos(-1.0) #define LL long long //#define mp make_pair #define pb emplace_back #define ls rt<<1, l, m #define rs rt<<1|1, m+1, r #define ULL unsigned LL #define pll pair<LL, LL> #define pli pair<LL, int> #define pii pair<int, int> #define piii pair<pii, int> #define pdd pair<double, double> #define mem(a, b) memset(a, b, sizeof(a)) #define debug(x) cerr << #x << " = " << x << "\n"; #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); //head const int N = 1e5 + 5; vector<int> g[N], rg[N]; queue<int> q; int in[N], T, Q, n, m, u, v, dp[N], anc[N][18]; inline int lca(int u, int v) { if(dp[u] < dp[v]) swap(u, v); for (int i = 17; i >= 0; --i) if(dp[anc[u][i]] >= dp[v]) u = anc[u][i]; if(u == v) return u; for (int i = 17; i >= 0; --i) if(anc[u][i] != anc[v][i]) u = anc[u][i], v = anc[v][i]; return anc[u][0]; } int main() { scanf("%d", &T); while(T--) { scanf("%d %d", &n, &m); for (int i = 1; i <= m; ++i){ scanf("%d %d", &u, &v); g[v].pb(u); in[u]++; rg[u].pb(v); } for (int i = 1; i <= n; ++i) if(!in[i]) q.push(i); while(!q.empty()) { int u = q.front(); q.pop(); int l; if(rg[u].size() == 0) l = 0; else { l = rg[u][0]; for (int i = 1; i < rg[u].size(); ++i) { int v = rg[u][i]; l = lca(l, v); } } anc[u][0] = l; for (int i = 1; i < 18; ++i) anc[u][i] = anc[anc[u][i-1]][i-1]; dp[u] = dp[l]+1; for (int v : g[u]) { in[v]--; if(!in[v]) q.push(v); } } scanf("%d", &Q); while(Q--) { scanf("%d %d", &u, &v); printf("%d\n", dp[u]+dp[v]-dp[lca(u, v)]); } for (int i = 0; i <= n; ++i) g[i].clear(), rg[i].clear(), in[i] = 0; } return 0; }
1003
1004
队友补了
1005
1006
思路:首先要知道一个公式:$(p-1)!\%p = p-1$。这个公式好像叫威尔逊定理。然后因为素数之间的距离很近,我们可以暴力往前找那个素数$Q$,
只要先预处理$1e7$以内的素数就可以了。最后把那个公式的阶乘除到$Q!$,还有一点要注意$1e14$做乘法会爆,要用__int128或者快速乘。
代码:
#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include<bits/stdc++.h> using namespace std; #define y1 y11 #define fi first #define se second #define pi acos(-1.0) #define LL long long //#define mp make_pair #define pb emplace_back #define ls rt<<1, l, m #define rs rt<<1|1, m+1, r #define ULL unsigned LL #define pll pair<LL, LL> #define pli pair<LL, int> #define pii pair<int, int> #define piii pair<pii, int> #define pdd pair<double, double> #define mem(a, b) memset(a, b, sizeof(a)) #define debug(x) cerr << #x << " = " << x << "\n"; #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); //head const int N = 1e7 + 5; LL MOD; LL q_pow(__int128 n, __int128 k) { __int128 res = 1; while(k) { if(k&1) res = (res * n) % MOD; n = (n*n) % MOD; k >>= 1; } return (LL)res; } int prime[N], cnt; bool not_p[N]; void init() { for (int i = 2; i < N; ++i) { if(!not_p[i]) prime[++cnt] = i; for (int j = 1; j <= cnt && i*prime[j] < N; ++j) { not_p[i*prime[j]] = true; if(i%prime[j] == 0) break; } } } int T; int main() { init(); scanf("%d", &T); while(T--) { scanf("%lld", &MOD); LL now; for (now = MOD-1; ; --now) { bool f = true; for (int j = 1; prime[j]*1LL*prime[j] <= now; ++j) { if(now%prime[j] == 0) { f = false; break; } } if(f) break; } __int128 ans = (MOD-1)%MOD; for (LL i = MOD-1; i > now; --i) ans = (ans * q_pow(i, MOD-2))%MOD; printf("%lld\n", (LL)ans); } return 0; }
1007
思路:离散化+线段树。对于每个位置在前$i-1$个数中,找一个$k$使得前$k$大加起来大于等于$sum_i-m$。为什么一做到这种题就想到Splay。
代码:
#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include<bits/stdc++.h> using namespace std; #define y1 y11 #define fi first #define se second #define pi acos(-1.0) #define LL long long //#define mp make_pair #define pb emplace_back #define ls rt<<1, l, m #define rs rt<<1|1, m+1, r #define ULL unsigned LL #define pll pair<LL, LL> #define pli pair<LL, int> #define pii pair<int, int> #define piii pair<pii, int> #define pdd pair<double, double> #define mem(a, b) memset(a, b, sizeof(a)) #define debug(x) cerr << #x << " = " << x << "\n"; #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); //head const int N = 2e5 + 10; int ch[N][2], val[N], cnt[N], fa[N], sz[N], lazy[N], ncnt = 0, rt = 0; LL sum[N]; inline int ck(int x) { return ch[fa[x]][1] == x; } inline void push_up(int x) { sum[x] = sum[ch[x][0]] -val[x]*1LL*cnt[x] + sum[ch[x][1]]; sz[x] = sz[ch[x][0]] + sz[ch[x][1]] + cnt[x]; } void Rotate(int x) { int y = fa[x], z = fa[y]; int k = ck(x), w = ch[x][k^1]; ch[y][k] = w, fa[w] = y; ch[z][ck(y)] = x, fa[x] = z; ch[x][k^1] = y, fa[y] = x; push_up(y), push_up(x); } void Splay(int x, int goal = 0) { while(fa[x] != goal) { int y = fa[x], z = fa[y]; if(z != goal) { if(ck(x) == ck(y)) Rotate(y); else Rotate(x); } Rotate(x); } if(!goal) rt = x; } void Find(int x) { if(!rt) return ; int cur = rt; while(ch[cur][x>val[cur]] && x != val[cur]) cur = ch[cur][x>val[cur]]; Splay(cur); } void Insert(int x) { int cur = rt, p = 0; while(cur && val[cur] != x) { p = cur; cur = ch[cur][x>val[cur]]; } if(cur) cnt[cur]++; else { cur = ++ncnt; if(p) ch[p][x>val[p]] = cur; fa[cur] = p; ch[cur][0] = ch[cur][1] = 0; val[cur] = x; sum[cur] = 0; cnt[cur] = sz[cur] = 1; } Splay(cur); } int get(LL k) { int cur = rt, now = 0; while(true) { if(ch[cur][0] && k <= sum[ch[cur][0]]) cur = ch[cur][0]; else if(k > sum[ch[cur][0]] + abs(val[cur])*1LL*cnt[cur]) k -= sum[ch[cur][0]] + abs(val[cur])*1LL*cnt[cur], now += sz[ch[cur][0]]+cnt[cur], cur = ch[cur][1]; else { int tmp = (k-sum[ch[cur][0]]+abs(val[cur])-1)/abs(val[cur]); // cout << tmp << endl; now += sz[ch[cur][0]]+tmp; return now; } } } inline void init() { ncnt = rt = ch[0][0] = ch[0][1] = fa[0] = sz[0] = cnt[0] = val[0] = sum[0] = 0; } int n, m, T, a[N]; //void Output(int x) { // if(ch[x][0]) Output(ch[x][0]); // printf("%d ", val[x]); // if(ch[x][1]) Output(ch[x][1]); //} int main() { scanf("%d", &T); while(T--) { init(); scanf("%d %d", &n, &m); LL s = 0; for (int i = 1; i <= n; ++i) scanf("%d", &a[i]); for (int i = 1; i <= n; ++i) { s += a[i]; if(s <= m)printf("0"); else printf("%d", get(s-m)); Insert(-a[i]); if(i == n) printf(" \n"); else printf(" "); } } return 0; }
1008
队友补了
1009
思路:最小费用流。关于建图有一个优化的地方,每个位置和后面比他大元素连接时,这些比他大的元素构成递减序列,这样就可以少连很多条边,那么要保证每个位置可以跑多次,只有第一次才有费用,可以在某些点之间(自行考虑)多连一条容量无穷,费用为0的边。最后再加上Dijkstra的费用流板子,就可以跑$78ms$了。
代码:
#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include<bits/stdc++.h> using namespace std; #define y1 y11 #define fi first #define se second #define pi acos(-1.0) #define LL long long //#define mp make_pair #define pb push_back #define ls rt<<1, l, m #define rs rt<<1|1, m+1, r #define ULL unsigned LL #define pll pair<LL, LL> #define pli pair<LL, int> #define pii pair<int, int> #define piii pair<pii, int> #define pdd pair<double, double> #define mem(a, b) memset(a, b, sizeof(a)) #define debug(x) cerr << #x << " = " << x << "\n"; #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); //head const int N = 4e3 + 10; const int INF = 0x3f3f3f3f; struct edge { int to, cap, cost, rev; }; int V, a[N]; vector<edge>g[N]; int h[N], dis[N], prevv[N], preve[N]; void add_edge(int u, int v, int cap, int cost) { g[u].pb({v, cap, cost, g[v].size()}); g[v].pb({u, 0, -cost, g[u].size()-1}); } int min_cost_flow(int s, int t, int f) { int res = 0; mem(h, 0); while(f > 0) { priority_queue<pii, vector<pii>, greater<pii> > q; mem(dis, 0x3f); dis[s] = 0; q.push({0, s}); while(!q.empty()) { pii p = q.top(); q.pop(); int v = p.se; if(dis[v] < p.fi) continue; for (int i = 0; i < g[v].size(); ++i) { edge &e = g[v][i]; if(e.cap > 0 && dis[e.to] > dis[v] + e.cost + h[v] - h[e.to]) { dis[e.to] = dis[v] + e.cost + h[v] - h[e.to]; prevv[e.to] = v; preve[e.to] = i; q.push({dis[e.to], e.to}); } } } if(dis[t] == INF) return -1; for (int v = 0; v < V; ++v) h[v] += dis[v]; int d = f; for (int v = t; v != s; v = prevv[v]) d = min(d, g[prevv[v]][preve[v]].cap); f -= d; res += d*h[t]; for (int v = t; v != s; v = prevv[v]) { edge &e = g[prevv[v]][preve[v]]; e.cap -= d; g[v][e.rev].cap += d; } } return res; } int main(){ int T; scanf("%d", &T); while(T--) { int n,k; scanf("%d%d", &n, &k); int s = 0, t = 2 * n + 1, ss = t+1; V = ss+1; for(int i=1; i<=n; i++) { scanf("%d", &a[i]); add_edge(i, i+n, 1, -1*a[i]); add_edge(i, i+n, INF, 0); } for(int i=1; i<=n; i++) { add_edge(s, i, 1, 0); add_edge(i + n, t, 1, 0); int now = INT_MAX; for(int j=i+1; j<=n; j++) { if(a[i] <= a[j] && a[j] < now) { add_edge(i+n, j, INF, 0); now = min(now, a[j]); } } } add_edge(ss, s, k, 0); printf("%lld\n", -min_cost_flow(ss, t, k)); for (int i = 0;i < V; ++i) g[i].clear(); } return 0; }
1010
1011
队友补了
2019 Multi-University Training Contest 4
Solved | Pro.ID | Title |
1001 | AND Minimum Spanning Tree | |
1002 | Colored Tree | |
1003 | Divide the Stones | |
1004 | Enveloping Convex | |
1005 | Good Numbers | |
1006 | Horse | |
1007 | Just an Old Puzzle | |
1008 | K-th Closest Distance | |
1009 | Linear Functions | |
1010 | Minimal Power of Prime |
1001
思路:如果$n==2^p-1$,那么最小权值是1;否则最小权值是0。$f_i$为最小的$2^p$使得$i\&{2}^{p} == 0$。
代码:
#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include<bits/stdc++.h> using namespace std; #define y1 y11 #define fi first #define se second #define pi acos(-1.0) #define LL long long //#define mp make_pair #define pb emplace_back #define ls rt<<1, l, m #define rs rt<<1|1, m+1, r #define ULL unsigned LL #define pll pair<LL, LL> #define pli pair<LL, int> #define pii pair<int, int> #define piii pair<pii, int> #define pdd pair<double, double> #define mem(a, b) memset(a, b, sizeof(a)) #define debug(x) cerr << #x << " = " << x << "\n"; #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); //head const int N = 2e5 + 5; int T, n, p[21], ans[N]; int main() { p[0] = 1; for (int i = 1; i <= 20; ++i) p[i] = p[i-1]*2; scanf("%d", &T); while(T--) { scanf("%d", &n); int res = 0; bool f = true; for (int i = 1; i < 20; ++i) { if(n == p[i]-1) { f = false; break; } } if(f) res = 0; else res = 1; printf("%d\n", res); if(f) { for (int i = 2; i <= n; ++i) { if(i%2 == 0) ans[i] = 1; else { int now = 0; for (int j = 0; j <= 20; ++j) { if(p[j] <= n && (p[j]&i) == 0) { ans[i] = p[j]; break; } } } } } else { ans[n] = 1; for (int i = 2; i < n; ++i) { if(i%2 == 0) ans[i] = 1; else { int now = 0; for (int j = 0; j <= 20; ++j) { if(p[j] <= n && (p[j]&i) == 0) { ans[i] = p[j]; break; } } } } } for (int i = 2; i <= n; ++i) printf("%d%c", ans[i], " \n"[i==n]); } return 0; }
1002
1003
思路:构造。打表找规律。
代码:
#include<bits/stdc++.h> #define ll long long using namespace std; const int maxn=1e5+10; vector<int> vs[maxn]; int main(){ int T; scanf("%d",&T); while(T--){ int n,k; scanf("%d %d",&n,&k); if(n==k){ if(n==1) { printf("yes\n"); printf("1\n");} else { printf("no\n"); } continue; } ll num=1ll*(1+n)*n/2; if(num%k!=0){ printf("no\n"); continue; } int x=n/k;int c=1; if(x%2==1){ if(k%2==0){ printf("no\n"); continue; } for(int i=1;i<=x;i++){ if(i==1){ for(int j=1;j<=k;j++) { vs[j].push_back(c); c++;} for(int j=k;j>=1;j-=2) { vs[j].push_back(c); c++; } for(int j=k-1;j>=1;j-=2){ vs[j].push_back(c); c++; } for(int j=k-1;j>=1;j-=2){vs[j].push_back(c); c++; } for(int j=k;j>=1;j-=2) {vs[j].push_back(c); c++; } i++; i++; } else { for(int j=1;j<=k;j++) { vs[j].push_back(c); c++;} for(int j=k;j>=1;j--) {vs[j].push_back(c); c++;} i++; } } } else { for(int i=1;i<=x;i++){ for(int j=1;j<=k;j++) { vs[j].push_back(c); c++;} for(int j=k;j>=1;j--) {vs[j].push_back(c); c++;} i++; } } printf("yes\n"); for(int i=1;i<=k;i++){ for(int j=0;j<vs[i].size();j++){ if(j!=0) printf(" "); printf("%d",vs[i][j]); } printf("\n"); vs[i].clear(); } } }
1004
1005
1006
思路:斜率优化dp。维护递增斜率$\frac{dp[j]-dp[k]+s[k]-s[j]+j*sum[j]-k*sum[k]}{sum[j]-sum[k]}$,其中$sum_i$表示前缀和,$s_i$表示前缀和的前缀和。
代码:
#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include<bits/stdc++.h> using namespace std; #define y1 y11 #define fi first #define se second #define pi acos(-1.0) #define LL long long //#define mp make_pair #define pb emplace_back #define ls rt<<1, l, m #define rs rt<<1|1, m+1, r #define ULL unsigned LL #define pll pair<LL, LL> #define pli pair<LL, int> #define pii pair<int, int> #define piii pair<pii, int> #define pdd pair<double, double> #define mem(a, b) memset(a, b, sizeof(a)) #define debug(x) cerr << #x << " = " << x << "\n"; #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); //head const int N = 1e4 + 10; int T, n, k, m, h[N]; vector<int> vc; LL dp[N][55], sum[N], s[N]; deque<int> q[55]; inline LL up(int k, int j, int p) { return dp[j][p]-dp[k][p]+s[k]-s[j]+j*sum[j]-k*sum[k]; } inline LL dw(int k, int j) { return sum[j]-sum[k]; } inline bool g(int k, int j, LL c, int p) { return up(k, j, p) <= c*dw(k, j); } inline bool gg(int k, int j, int i, int p) { return up(k, j, p)*dw(j, i) >= up(j, i, p)*dw(k, j); } int main() { scanf("%d", &T); while(T--) { vc.clear(); scanf("%d %d %d", &n, &k, &m); for (int i = 1; i <= n; ++i) scanf("%d", &h[i]), vc.pb(h[i]*(n-i+1)), sum[i] = sum[i-1]+h[i], s[i] = s[i-1]+sum[i]; for (int i = 0; i <= n; ++i) for (int j = 0; j <= k+1; ++j) dp[i][j] = 1LL<<60; dp[0][0] = 0; sort(vc.begin(), vc.end(), greater<int>()); LL ans = 0; for (int i = 0; i < m; ++i) ans += vc[i]; for (int i = 0; i <= k+1; ++i) q[i].clear(); q[0].push_back(0); for (int i = 1; i <= n; ++i) { for (int j = k; j >= 0; --j) { while(q[j].size() >= 2) { int a = q[j].front(); q[j].pop_front(); int b = q[j].front(); if(g(a, b, i, j)) ; else { q[j].push_front(a); break; } } if(!q[j].empty()) { int x = q[j].front(); dp[i][j+1] = dp[x][j]+s[i]-s[x]-(i-x)*sum[x]; while(q[j+1].size() >= 2) { int b = q[j+1].back(); q[j+1].pop_back(); int a = q[j+1].back(); if(gg(a, b, i, j+1)) ; else { q[j+1].push_back(b); break; } } q[j+1].push_back(i); } } } LL tmp = 1LL<<60; for (int j = 1; j <= k+1; ++j) tmp = min(tmp, dp[n][j]); printf("%lld\n", ans-tmp); } return 0; }
1007
思路:将0看成16,0每移动一个位置会改变奇数个逆序数,所以逆序数和移动距离奇偶性相同。
代码:
#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include<bits/stdc++.h> using namespace std; #define y1 y11 #define fi first #define se second #define pi acos(-1.0) #define LL long long //#define mp make_pair #define pb emplace_back #define ls rt<<1, l, m #define rs rt<<1|1, m+1, r #define ULL unsigned LL #define pll pair<LL, LL> #define pli pair<LL, int> #define pii pair<int, int> #define piii pair<pii, int> #define pdd pair<double, double> #define mem(a, b) memset(a, b, sizeof(a)) #define debug(x) cerr << #x << " = " << x << "\n"; #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); //head int T, n, a[10][10]; vector<int> vc; int main() { scanf("%d", &T); while(T--) { vc.clear(); int ans = 0, d = 0; for (int i = 1; i <= 4; ++i) for (int j = 1; j <= 4; ++j) { scanf("%d", &a[i][j]); if(a[i][j] == 0) a[i][j] = 16, d = (4-i)+(4-j); vc.pb(a[i][j]); } for (int i = 0; i < vc.size(); ++i) { for (int j = i+1; j< vc.size(); ++j) { if(vc[i] > vc[j]) ans++; } } if(ans%2 == d%2) printf("Yes\n"); else printf("No\n"); } return 0; }
1008
思路:先建立一颗划分树。然后对于每个查询我们二分答案$mid$,那么就是找$L$到$R$这段区间有多少个数值在区间$[p-mid, p+mid]$,这个可以在划分树上每个节点二分实现。
单次查询复杂度$O(log(n)^3)$。
代码:
#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> 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 = 998244353; 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 = 1e5+9; int a[maxn]; vector<int> vec[maxn<<2]; inline void build(int le, int ri, int rt) { vec[rt].clear(); if(le == ri) { vec[rt].pb(a[le]); return; } int mid = (le + ri) >> 1; build(le, mid, rt<<1); build(mid+1, ri, rt<<1|1); int p1 = 0, p2 = 0; while(p1 < vec[rt<<1].size() && p2 < vec[rt<<1|1].size()) { if(vec[rt<<1][p1] < vec[rt<<1|1][p2]) { vec[rt].pb(vec[rt<<1][p1]); p1++; } else { vec[rt].pb(vec[rt<<1|1][p2]); p2++; } } while(p1 < vec[rt<<1].size()) { vec[rt].pb(vec[rt<<1][p1]); p1++; } while(p2 < vec[rt<<1|1].size()) { vec[rt].pb(vec[rt<<1|1][p2]); p2++; } return ; } inline int query(int L, int R ,int x, int y, int le, int ri, int rt) { if(le >= L && ri <= R) return upper_bound(vec[rt].begin(), vec[rt].end(), y) - lower_bound(vec[rt].begin(), vec[rt].end(), x); int mid = (le + ri) >> 1; int res = 0; if(mid >= L) res += query(L, R, x, y ,le, mid, rt<<1); if(mid < R) res += query(L, R, x, y, mid+1, ri, rt<<1|1); return res; } int main(){ int T; read(T); while(T--){ int n,m; read(n); read(m); for(int i=1; i<=n; i++) read(a[i]); int X = 0; build(1, n, 1); for(int i=1; i<=m; i++) { int tl, tr,tp,tk; read(tl); read(tr); read(tp); read(tk); int l,r,p,k; l = tl ^ X; r = tr ^ X; p = tp ^ X; k = tk ^ X; int le = 0, ri = 1000000, mid = (le+ri) >> 1; while(le < ri) { if(query(l, r, p - mid, p + mid, 1, n, 1) >= k) ri = mid; else le = mid+1; mid = (le+ri) >> 1; } X = mid; printf("%d\n", X); } } return 0; }
1009
1010
思路:先把$5e3$以内的质因子筛掉,然后剩下的质因子的幂次最多是四次,特判一下$p^4$,$p^3$,$p^2$ ,$p_1^{2}p_2^2$这四种情况,
否则剩下的就是一个质因子幂次是1的情况。
代码:
#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include<bits/stdc++.h> using namespace std; #define y1 y11 #define fi first #define se second #define pi acos(-1.0) #define LL long long //#define mp make_pair #define pb emplace_back #define ls rt<<1, l, m #define rs rt<<1|1, m+1, r #define ULL unsigned LL #define pll pair<LL, LL> #define pli pair<LL, int> #define pii pair<int, int> #define piii pair<pii, int> #define pdd pair<double, double> #define mem(a, b) memset(a, b, sizeof(a)) #define debug(x) cerr << #x << " = " << x << "\n"; #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); //head const int N = 1e6 + 5, M = 5e3 + 5; int T; LL n; vector<int> vc; bool not_p[N]; int prime[N], cnt = 0; inline void init() { for (int i = 2; i < N; ++i) { if(!not_p[i]) { prime[++cnt] = i; if(i < M) vc.pb(i); } for (int j = 1; j <= cnt && i * prime[j] < N; ++j ) { not_p[i*prime[j]] = true; if(i%prime[j] == 0) break; } } } int main() { init(); scanf("%d", &T); while(T--) { scanf("%lld", &n); int ans = 1000; for (int x : vc) { int cnt = 0; while(n%x == 0) n /= x, ++cnt; if(cnt) ans = min(ans, cnt); } if(n != 1) { bool f = false; LL x = pow(n*1.0, 1.0/4); while(x*x*x*x < n) ++x; while(x*x*x*x > n) --x; if(x*x*x*x == n && !not_p[x]) ans = min(ans, 4), f = true; if(!f) { x = pow(n*1.0, 1.0/3); while(x*x*x < n) ++x; while(x*x*x > n) --x; if(x*x*x == n && !not_p[x]) ans = min(ans, 3), f = true; } if(!f) { x = sqrt(n*1.0); while(x*x < n) ++x; while(x*x > n) --x; if(x*x == n) ans = min(ans, 2), f = true; } if(!f) ans = min(ans, 1); } if(ans == 1000) ans = 1; printf("%d\n", ans); } return 0; }
2019 Multi-University Training Contest 5
Solved | Pro.ID | Title |
1001 | fraction | |
1002 | three arrays | |
1003 | geometric problem | |
1004 | equation | |
1005 | permutation 1 | |
1006 | string matching | |
1007 | permutation 2 | |
1008 | line symmetric | |
1009 | discrete logarithm problem | |
1010 | find hidden array |
1001
思路:按照官方题解化出的式子,就是51Nod 1187 寻找分数,用类欧求解。
代码:
#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include<bits/stdc++.h> using namespace std; #define y1 y11 #define fi first #define se second #define pi acos(-1.0) #define LL long long //#define mp make_pair #define pb push_back #define ls rt<<1, l, m #define rs rt<<1|1, m+1, r #define ULL unsigned LL #define pll pair<LL, LL> #define pli pair<LL, int> #define pii pair<int, int> #define piii pair<pii, int> #define pdd pair<double, double> #define mem(a, b) memset(a, b, sizeof(a)) #define debug(x) cerr << #x << " = " << x << "\n"; #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); //head int T; LL a, b, c, d, p, q, P, X; //a/b < p/q < c/d void solve(LL a, LL b, LL c, LL d) { if(a == 0) { p = 1; q = d/c+1; return ; } if(a >= b) { solve(a%b, b, c-(a/b)*d, d); p += (a/b)*q; return ; } if(c > d) { p = q = 1; return ; } solve(d, c, b, a); swap(p, q); } int main() { scanf("%d", &T); while(T--) { scanf("%lld %lld", &P, &X); a = P, b = X, c = P, d = X-1; solve(a, b, c, d); printf("%lld/%lld\n", p*X-P*q, p); } return 0; }
1002
思路:01字典树上贪心,建两颗字典树,每次能同方向走就同方向走。
代码:
#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include<bits/stdc++.h> using namespace std; #define y1 y11 #define fi first #define se second #define pi acos(-1.0) #define LL long long //#define mp make_pair #define pb push_back #define ls rt<<1, l, m #define rs rt<<1|1, m+1, r #define ULL unsigned LL #define pll pair<LL, LL> #define pli pair<LL, int> #define pii pair<int, int> #define piii pair<pii, int> #define pdd pair<double, double> #define mem(a, b) memset(a, b, sizeof(a)) #define debug(x) cerr << #x << " = " << x << "\n"; #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); //head const int N = 1e5 + 5; int a[N], b[N], n, T; vector<int> vc; struct Trie { int trie[N*30][2], cnt[N*30], tot; inline void clr() { for (int i = 0; i <= tot; ++i) trie[i][0] = trie[i][1] = cnt[i] = 0; tot = 0; } inline void ins(int x) { int rt = 0; for (int i = 29; i >= 0; --i) { int id = (x>>i)&1; if(!trie[rt][id]) trie[rt][id] = ++tot; rt = trie[rt][id]; cnt[rt]++; } } }A, B; inline int solve() { int ra = 0, rb = 0, res = 0; for (int i = 29; i >= 0; --i) { if(A.cnt[A.trie[ra][0]] && B.cnt[B.trie[rb][0]]) { ra = A.trie[ra][0]; rb = B.trie[rb][0]; A.cnt[ra]--; B.cnt[rb]--; } else if(A.cnt[A.trie[ra][1]] && B.cnt[B.trie[rb][1]]) { ra = A.trie[ra][1]; rb = B.trie[rb][1]; A.cnt[ra]--; B.cnt[rb]--; } else if(A.cnt[A.trie[ra][0]] && B.cnt[B.trie[rb][1]]){ ra = A.trie[ra][0]; rb = B.trie[rb][1]; A.cnt[ra]--; B.cnt[rb]--; res |= 1<<i; } else { ra = A.trie[ra][1]; rb = B.trie[rb][0]; A.cnt[ra]--; B.cnt[rb]--; res |= 1<<i; } } return res; } int main() { scanf("%d", &T); while(T--) { scanf("%d", &n); A.clr(), B.clr(); for (int i = 1; i <= n; ++i) scanf("%d", &a[i]), A.ins(a[i]); for (int i = 1; i <= n; ++i) scanf("%d", &b[i]), B.ins(b[i]); vc.clear(); for (int i = 1; i <= n; ++i) vc.pb(solve()); sort(vc.begin(), vc.end()); for (int i = 0; i < n; ++i) printf("%d%c", vc[i], " \n"[i+1==n]); } return 0; }
1003
1004
思路:暴力。按$\frac{-b}{a}$排序,然后枚举以相邻两个值作为$x$的范围。
代码:
#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include<bits/stdc++.h> using namespace std; #define y1 y11 #define fi first #define se second #define pi acos(-1.0) #define LL long long //#define mp make_pair #define pb emplace_back #define ls rt<<1, l, m #define rs rt<<1|1, m+1, r #define ULL unsigned LL #define pll pair<LL, LL> #define pli pair<LL, int> #define pii pair<int, int> #define piii pair<pii, int> #define pdd pair<double, double> #define mem(a, b) memset(a, b, sizeof(a)) #define debug(x) cerr << #x << " = " << x << "\n"; #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); //head const int N = 1e5 + 5; int n, T, c, suma[N], sumb[N], sufa[N], sufb[N]; pii a[N]; vector<pii> res; bool cmp(pii x, pii y) { return -x.se*1LL*y.fi < -y.se*1LL*x.fi; } bool _cmp(pii x, pii y) { return x.se*1LL*y.fi < y.se*1LL*x.fi; } int main() { scanf("%d", &T); while(T--) { scanf("%d %d", &n, &c); for (int i = 1; i <= n; ++i) scanf("%d %d", &a[i].fi, &a[i].se); sort(a+1, a+1+n, cmp); for (int i = 1; i <= n; ++i) suma[i]=suma[i-1]+a[i].fi, sumb[i] = sumb[i-1]+a[i].se; sufa[n+1] = sufb[n+1] = 0; for (int i = n; i >= 1; --i) sufa[i] = sufa[i+1]-a[i].fi, sufb[i] = sufb[i+1]-a[i].se; bool f = false; for (int i = 0; i <= n; ++i) { LL sa = suma[i]+sufa[i+1]; LL sb = sumb[i]+sufb[i+1]; LL up = c-sb; LL dw = sa; //cout << sa << " " << up << endl; if(dw == 0) { if(up == 0) { //cout << a[i].se*1LL*a[i+1].fi << " 11111 " << a[i].se*1LL*a[i-1].fi << endl; if(i == 0 || i == n) f = true; else if(a[i].se*1LL*a[i+1].fi != a[i+1].se*1LL*a[i].fi) f = true; } } else { LL d = __gcd(dw, up); dw /= d, up /= d; if(dw < 0) dw = -dw, up = -up; if(dw > 0) { if(i == 0) { if(up*a[i+1].fi <= -a[i+1].se*dw) res.pb(dw, up); } else if(i == n) { if(up*a[i].fi >= -a[i].se*dw) res.pb(dw, up); } else { if(up*a[i+1].fi <= -a[i+1].se*dw && up*a[i].fi >= -a[i].se*dw) res.pb(dw, up); } } else { if(i == 0) { if(up*a[i+1].fi >= -a[i+1].se*dw) res.pb(dw, up); } else if(i == n) { if(up*a[i].fi <= -a[i].se*dw) res.pb(dw, up); } else { if(up*a[i+1].fi >= -a[i+1].se*dw && up*a[i].fi <= -a[i].se*dw) res.pb(dw, up); } } } } if(f) printf("-1\n"); else { sort(res.begin(), res.end()); res.erase(unique(res.begin(), res.end()), res.end()); sort(res.begin(), res.end(), _cmp); if(res.size() != 0) { printf("%d ", (int)res.size()); int tot = 0; for (pii p : res) { ++tot; printf("%d/%d%c", p.se, p.fi, " \n"[tot==res.size()]); } } else printf("0\n"); } res.clear(); } return 0; }
1005
思路:分类讨论,当$k$大于$(n-2)!$时,$n!$不会太大,直接暴力算,否则固定第一个为$n$,第二个为$1$,算出后面$n-2$个数排列的第$k$大。
代码:
#include<bits/stdc++.h> #define ll long long using namespace std; const int maxn=1e4+10; int k[maxn]; int a[maxn*55][21]; int n,num, id[maxn*55]; bool cmp(int x, int y) { for (int i = 1; i < n; ++i) { if(a[x][i]-a[x][i-1] < a[y][i]-a[y][i-1]) return 1; else if(a[x][i]-a[x][i-1] > a[y][i]-a[y][i-1]) return 0; } return 1; } int main(){ int T; scanf("%d",&T); while(T--){ scanf("%d %d",&n,&num); int temp=0; ll t=1; for(int i=1;i<n-1;i++) t=t*i; int tot = 0; if(t>=num){ k[0] = n; k[1] = 1; for (int i = 2; i < n; ++i) k[i] = i; do{ tot++; for(int i=0;i<=n-1;i++) a[tot][i]=k[i]; if(tot >= 40320) break; } while(next_permutation(k+2,k+n)); } else { for(int i=0;i<=n-1;i++) k[i]=i+1; do{ tot++; for(int i=0;i<=n-1;i++) a[tot][i]=k[i]; } while(next_permutation(k,k+1+n-1)); } for (int i = 1; i <= tot; ++i) id[i] = i; nth_element(id+1, id+num, id+1+tot, cmp); for (int i = 0; i < n; ++i) printf("%d%c", a[id[num]][i], " \n"[i==n-1]); } }
1006
思路:exkmp。
代码:
#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include<bits/stdc++.h> using namespace std; #define y1 y11 #define fi first #define se second #define pi acos(-1.0) #define LL long long //#define mp make_pair #define pb emplace_back #define ls rt<<1, l, m #define rs rt<<1|1, m+1, r #define ULL unsigned LL #define pll pair<LL, LL> #define pli pair<LL, int> #define pii pair<int, int> #define piii pair<pii, int> #define pdd pair<double, double> #define mem(a, b) memset(a, b, sizeof(a)) #define debug(x) cerr << #x << " = " << x << "\n"; #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); //head const int N = 1e6 + 5; int T, n; char s[N], t[N]; int nxt[N], ex[N]; void GETNEXT(char *str) { int i = 0, j, po, len=strlen(str); nxt[0] = len; while(str[i] == str[i+1] && i+1 < len) i++; nxt[1] = i; po = 1; for(i = 2; i < len; i++) { if(nxt[i-po] + i < nxt[po] + po) nxt[i] = nxt[i-po]; else { j=nxt[po] + po - i; if(j < 0) j = 0; while(i + j < len && str[j] == str[j+i]) j++; nxt[i] = j; po = i; } } } void EXKMP(char *s1,char *s2) { int i = 0, j, po, len = strlen(s1), l2=strlen(s2); GETNEXT(s2); while(s1[i] == s2[i] && i < l2 && i < len) i++; ex[0] = i; po = 0; for(i = 1; i < len; i++) { if(nxt[i-po] + i < ex[po] + po) ex[i]=nxt[i-po]; else { j = ex[po] + po - i; if(j < 0) j = 0; while(i + j < len && j < l2 && s1[j+i] == s2[j]) j++; ex[i] = j; po = i; } } } int main() { scanf("%d", &T); while(T--) { scanf("%s", s); n = strlen(s); for (int i = 0; i <= n; ++i) t[i] = s[i]; EXKMP(s, t); LL ans = 0; for (int i = 1; i < n; ++i) { if(ex[i]+i == n) ans += ex[i]; else ans += ex[i]+1; //cout << ans << endl; } printf("%lld\n", ans); } return 0; }
1007
思路:我们发现从$x$到$x+1$以及$y-1$到$y$的方案是固定的(每次跳两格到边界再跳回来),那么答案只根$x$和$y$的间距有关系了,我们打表找规律。
然后再处理一些特殊情况就好了。
代码:
#include<bits/stdc++.h> using namespace std; const int mod=998244353; const int maxn=1e5+10; int a[maxn]; int f[maxn]; int main(){ //a[1]=1; a[2]=2; a[3]=3; a[4]=4; f[0]=1; f[1]=1; f[2]=1; f[3]=2; f[4]=3; for(int i=5;i<maxn;i++){ f[i]=f[i-1]+f[i-3]; f[i]=f[i]%mod; //a[i]=a[i-1]+f[i]; a[i]=a[i]%mod; } //for(int i=1;i<=10;i++) cout<<f[i]<<endl; int T; scanf("%d",&T); while(T--){ int n,x,y; scanf("%d %d %d",&n,&x,&y); if(x+1==y){ if(x>=2 && x<=n-2) printf("0\n"); else printf("1\n"); continue; } if(x!=1) x++; if(y!=n) y--; printf("%d\n",f[y-x]); } }
1008
队友补了
1009
1010
2019 Multi-University Training Contest 6
Solved | Pro.ID | Title |
1001 | Salty Fish | |
1002 | Nonsense Time | |
1003 | Milk Candy | |
1004 | Speed Dog | |
1005 | Snowy Smile | |
1006 | Faraway | |
1007 | Support or Not | |
1008 | TDL | |
1009 | Three Investigators | |
1010 | Ridiculous Netizens | |
1011 | 11 Dimensions | |
1012 | Stay Real |
1001
1002
思路:由于数据随机,所以最长上升子序列期望长度是$\sqrt{n}$。所以从后往前算,每次如果一个元素是在最长上升子序列中就重新算一边最长上升子序列。
复杂度$\sqrt{n}*n*log(n)$。
代码:
#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include<bits/stdc++.h> using namespace std; #define y1 y11 #define fi first #define se second #define pi acos(-1.0) #define LL long long //#define mp make_pair #define pb push_back #define ls rt<<1, l, m #define rs rt<<1|1, m+1, r #define ULL unsigned LL #define pll pair<LL, LL> #define pli pair<LL, int> #define pii pair<int, int> #define piii pair<pii, int> #define pdd pair<double, double> #define mem(a, b) memset(a, b, sizeof(a)) #define debug(x) cerr << #x << " = " << x << "\n"; #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); //head const int N = 5e4 + 5; const int INF = 0x3f3f3f3f; int a[N], k[N], dp[N], ans[N], pre[N], n, T; bool vis[N]; ///递增序列中 bool vv[N]; ///被冻住 inline int cal() { fill(dp, dp+n, INF); fill(pre, pre+n+1, 0); fill(vis+1, vis+n+1, false); for (int i = 1; i <= n; ++i) { if(vv[a[i]]) continue; int p = lower_bound(dp, dp+n, a[i])-dp; if(p) pre[a[i]] = dp[p-1]; dp[p] = a[i]; } int p = lower_bound(dp, dp+n, INF)-dp; int t = dp[p-1]; while(t) { vis[t] = true; t = pre[t]; } return p; } int main() { scanf("%d", &T); while(T--) { scanf("%d", &n); for(int i = 1; i <= n; ++i) scanf("%d", &a[i]); for(int i = 1; i <= n; ++i) scanf("%d", &k[i]); fill(vv+1, vv+n+1, false); int c = cal(); for (int i = n; i >= 1; --i) { ans[i] = c; vv[a[k[i]]] = true; if(vis[a[k[i]]]) c = cal(); } for (int i = 1; i <= n; ++i) printf("%d%c", ans[i], " \n"[i==n]); } return 0; }
1003
1004
1005
思路:枚举上下边界,用线段树维护最大字段和。
代码:
#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include<bits/stdc++.h> using namespace std; #define y1 y11 #define fi first #define se second #define pi acos(-1.0) #define LL long long //#define mp make_pair #define pb emplace_back #define ls rt<<1, l, m #define rs rt<<1|1, m+1, r #define ULL unsigned LL #define pll pair<LL, LL> #define pli pair<LL, int> #define pii pair<int, int> #define piii pair<pii, int> #define pdd pair<double, double> #define mem(a, b) memset(a, b, sizeof(a)) #define debug(x) cerr << #x << " = " << x << "\n"; #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); //head const int N = 2e3 + 10; int n, T; LL v[N][N]; vector<int> vx, vy; vector<pair<int,LL>> vc[N]; piii a[N]; struct Node { LL mx, sum, l, r; }tree[N<<2]; inline void push_up(int rt) { tree[rt].sum = tree[rt<<1].sum+tree[rt<<1|1].sum; tree[rt].l = max(tree[rt<<1].l, tree[rt<<1].sum+tree[rt<<1|1].l); tree[rt].r = max(tree[rt<<1|1].r, tree[rt<<1|1].sum+tree[rt<<1].r); tree[rt].mx = max(max(tree[rt<<1].mx, tree[rt<<1|1].mx), tree[rt<<1].r+tree[rt<<1|1].l); } void build(int rt, int l, int r) { tree[rt].mx = tree[rt].sum = tree[rt].l = tree[rt].r = 0; if(l == r) return ; int m = l+r >> 1; build(ls); build(rs); } void update(int p, LL x, int rt, int l, int r) { if(l == r) { tree[rt].sum += x; tree[rt].l = max(0LL, tree[rt].sum); tree[rt].r = max(0LL, tree[rt].sum); tree[rt].mx = max(0LL, tree[rt].sum); return ; } int m = l+r >> 1; if(p <= m) update(p, x, ls); else update(p, x, rs); push_up(rt); } int main() { scanf("%d", &T); while(T--) { vx.clear(); vy.clear(); scanf("%d", &n); for (int i = 1; i <= n; ++i) { scanf("%d %d %d", &a[i].fi.fi, &a[i].fi.se, &a[i].se); vx.pb(a[i].fi.fi); vy.pb(a[i].fi.se); } sort(vx.begin(), vx.end()); vx.erase(unique(vx.begin(), vx.end()), vx.end()); sort(vy.begin(), vy.end()); vy.erase(unique(vy.begin(), vy.end()), vy.end()); for (int i = 1; i <= n; ++i) { a[i].fi.fi = lower_bound(vx.begin(), vx.end(), a[i].fi.fi)-vx.begin()+1; a[i].fi.se = lower_bound(vy.begin(), vy.end(), a[i].fi.se)-vy.begin()+1; } int upx = vx.size(), upy = vy.size(); for (int i = 0; i <= upx; ++i) for (int j = 0; j <= upy; ++j) v[i][j] = 0; for (int i = 1; i <= n; ++i) v[a[i].fi.fi][a[i].fi.se] += a[i].se; LL ans = 0; for (int i = 1; i <= upx; ++i) { for (int j = 1; j <= upy; ++j) { if(v[i][j]) vc[i].pb(j, v[i][j]); } } for (int i = 1; i <= upx; ++i) { build(1, 1, upy); for (int j = i; j <= upx; ++j) { for (auto p : vc[j]) update(p.fi, p.se, 1, 1, upy); ans = max(ans, tree[1].mx); } } printf("%lld\n", ans); for (int i = 0; i <= upx; ++i) vc[i].clear(); } return 0; }
1006
思路:先对横纵坐标排序去重,然后枚举每一个小矩形,对于每个小矩形,它的循环节是60*60的。
代码:
#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include<bits/stdc++.h> using namespace std; #define y1 y11 #define fi first #define se second #define pi acos(-1.0) #define LL long long //#define mp make_pair #define pb push_back #define ls rt<<1, l, m #define rs rt<<1|1, m+1, r #define ULL unsigned LL #define pll pair<LL, LL> #define pli pair<LL, int> #define pii pair<int, int> #define piii pair<pii, int> #define pdd pair<double, double> #define mem(a, b) memset(a, b, sizeof(a)) #define debug(x) cerr << #x << " = " << x << "\n"; #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); //head const int N = 15; int T, n, m; int x[N], y[N], k[N], t[N]; int sum[65][65]; vector<int> vx, vy; int main() { scanf("%d", &T); while(T--) { scanf("%d %d", &n, &m); vx.clear(), vy.clear(); for (int i = 1; i <= n; ++i) scanf("%d %d %d %d", &x[i], &y[i], &k[i], &t[i]), vx.pb(x[i]), vy.pb(y[i]); vx.pb(-1), vx.pb(m); vy.pb(-1), vy.pb(m); sort(vx.begin(), vx.end()); sort(vy.begin(), vy.end()); vx.erase(unique(vx.begin(), vx.end()), vx.end()); vy.erase(unique(vy.begin(), vy.end()), vy.end()); LL ans = 0; for (int i = 1; i < vx.size(); ++i) { for (int j = 1; j < vy.size(); ++j) { int x1 = vx[i-1]+1, y1 = vy[j-1]+1; int x2 = vx[i], y2 = vy[j]; for (int dx = 1; dx <= 60; ++dx) { for (int dy = 1; dy <= 60; ++dy) { bool f = true; for (int p = 1; p <= n; ++p) if((abs(x[p]-(x1+dx-1))+abs(y[p]-(y1+dy-1)))%k[p] != t[p]) {f = false; break;} if(f) sum[dx][dy] = sum[dx-1][dy]+sum[dx][dy-1]-sum[dx-1][dy-1]+1; else sum[dx][dy] = sum[dx-1][dy]+sum[dx][dy-1]-sum[dx-1][dy-1]; } } int dx = (x2-x1+1), dy = (y2-y1+1); ans += (dx/60)*1LL*(dy/60)*sum[60][60]; ans += sum[dx%60][dy%60]; ans += (dx/60)*1LL*sum[60][dy%60]; ans += (dy/60)*1LL*sum[dx%60][60]; } } printf("%lld\n", ans); } return 0; }
1007
1008
思路:暴力枚举
代码:
#include<bits/stdc++.h> #define ll long long using namespace std; int main(){ int T; scanf("%d",&T); while(T--){ ll k,m; scanf("%lld %lld",&k,&m); int flag=0; for(ll i=max(1ll,k-1000);i<=k+1000;i++){ int tot=0; for(ll j=i+1;;j++){ if(__gcd(i,j)==1) { tot++; if(tot==m){ if( (i^(j-i)^k)==0){ flag=1; printf("%lld\n",i); } break; } } } if(flag) break; } if(flag==0) printf("-1\n"); } }
1009
思路:每次向杨氏图表中第一层插入a[i]个a[i],将大于a[i]的顶到下一层(具体看题解),杨氏图表前5层个数就是答案。
代码:
#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include<bits/stdc++.h> using namespace std; #define y1 y11 #define fi first #define se second #define pi acos(-1.0) #define LL long long #define ll long long //#define mp make_pair #define pb push_back #define ls rt<<1, l, m #define rs rt<<1|1, m+1, r #define ULL unsigned LL #define pll pair<LL, LL> #define pli pair<LL, int> #define pii pair<int, int> #define piii pair<pii, int> #define pdd pair<double, double> #define mem(a, b) memset(a, b, sizeof(a)) #define debug(x) cerr << #x << " = " << x << "\n"; #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); //head const int N = 1e5 + 5; int a[N], T, n; map<int, LL> mp[5]; LL ans = 0; inline void ins(int x, int cnt, int a) { if(x == 5) return ; map<int, LL>:: iterator it; while(cnt) { it = mp[x].upper_bound(a); if(it == mp[x].end()) { ans += cnt; mp[x][a] += cnt; cnt = 0; } else { int mn = min((LL)cnt, it->se); it->se -= mn; if((it->se) == 0) mp[x].erase(it); ins(x+1, mn, it->fi); mp[x][a] += mn; cnt -= mn; } } } int main() { scanf("%d", &T); while(T--) { scanf("%d", &n); for (int i = 1; i <= n; ++i) scanf("%d", &a[i]); for (int i = 0; i < 5; ++i) mp[i].clear(); ans = 0; for (int i = 1; i <= n; ++i) { ins(0, a[i], a[i]); printf("%lld%c", ans, " \n"[i==n]); } } return 0; }
1010
1011
思路:dp
代码:
// #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() < 50) 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; } } } // // for(int i=1; i<=all; i++) { // for(int j=0; j<m; j++) { // cout<<dp[i][j]<<" "; // } // cout<<endl; // } 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\n", cur); } } return 0; }
1012
思路:优先队列模拟
代码:
// #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 = 998244353; 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 = 1e5+9; priority_queue<pll>que; int du[maxn], a[maxn]; int main(){ int T; scanf("%d", &T); while(T--) { int n; scanf("%d", &n); ll s1 = 0, s2 = 0; for(int i=0; i<=n; i++) du[i] = 0; for(int i=1; i<=n; i++) { scanf("%d", &a[i]); du[i/2] ++; } while(!que.empty()) que.pop(); for(int i=1; i<=n; i++) if(!du[i]) que.push(pll(a[i], i)); int flag = 1; while(!que.empty()) { pll f = que.top(); que.pop(); if(flag) {s1 += f.fi; flag = 0;} else {s2+=f.fi;flag = 1;} int u = f.se; du[u/2] --; if(du[u/2] == 0) que.push(pll(a[u/2], u/2)); } printf("%lld %lld\n", s1, s2); } return 0; }
2019 Multi-University Training Contest 7
Solved | Pro.ID | Title |
1001 | A + B = C | |
1002 | Bracket Sequences on Tree | |
1003 | Cuber Occurrence | |
1004 | Data Structure Problem | |
1005 | Equation | |
1006 | Final Exam | |
1007 | Getting Your Money Back | |
1008 | Halt Hater | |
1009 | Intersection of Prisms | |
1010 | Just Repeat | |
1011 | Kejin Player |
1001
思路:如果将$A$、$B$、$C$的后导零去掉,那么公式只有$A+B=C*10^z$,$A*10^x+B=C$,$A+B*10^y=C$三种情况,那么hash搞一搞。
代码:
#include<bits/stdc++.h> #define LL long long #define pb emplace_back using namespace std; const int MOD = 1e9 + 7; const int M2 = 1085438567; const int BS = 2e9; const int N = 1e5 + 5; LL p[N], p2[N]; LL q_pow(LL n, LL k, LL MOD) { LL res = 1; while(k) { if(k&1) res = (res*n) %MOD; n = (n*n)%MOD; k >>= 1; } return res; } unordered_map<LL, int> mp; void init() { p[0] = 1; p2[0] = 1; for (int i = 1; i < N; ++i) p[i] = p[i-1]*10%MOD, p2[i] = p2[i-1]*10%M2; for (int i = 0; i < N; ++i) mp[p[i]*BS+p2[i]] = i; } int T; char a[N], b[N], c[N]; LL A, B, C, AA, BB, CC; int main() { init(); scanf("%d", &T); while(T--) { scanf("%s", a); scanf("%s", b); scanf("%s", c); int la = strlen(a), lb = strlen(b), lc = strlen(c); int ca = 0, cb = 0, cc = 0; A = B = C = AA = BB = CC = 0; while(a[la-1] == \'0\') --la, ++ca; while(b[lb-1] == \'0\') --lb, ++cb; while(c[lc-1] == \'0\') --lc, ++cc; for (int i = 0; i < la; ++i) A = (A*10+a[i]-\'0\')%MOD, AA = (AA*10+a[i]-\'0\')%M2; for (int i = 0; i < lb; ++i) B = (B*10+b[i]-\'0\')%MOD, BB = (BB*10+b[i]-\'0\')%M2; for (int i = 0; i < lc; ++i) C = (C*10+c[i]-\'0\')%MOD, CC = (CC*10+c[i]-\'0\')%M2; int x, y, z; bool f = false; LL t = (A+B)*q_pow(C, MOD-2, MOD)%MOD; LL tt = (AA+BB)*q_pow(CC, M2-2, M2)%M2; if(mp.find(t*BS+tt) != mp.end()) { x = 0; y = 0; z = mp[t*BS+tt]; f = true; } t = ((C-B)*q_pow(A, MOD-2, MOD)%MOD+MOD)%MOD; tt = ((CC-BB)*q_pow(AA, M2-2, M2)%M2+M2)%M2; if(mp.find(t*BS+tt) != mp.end()) { x = mp[t*BS+tt]; y = 0; z = 0; f = true; } t = ((C-A)*q_pow(B, MOD-2, MOD)%MOD+MOD)%MOD; tt = ((CC-AA)*q_pow(BB, M2-2, M2)%M2+M2)%M2; if(mp.find(t*BS+tt) != mp.end()) { x = 0; y = mp[t*BS+tt]; z = 0; f = true; } x += max(ca, max(cb, cc)) - ca; y += max(ca, max(cb, cc)) - cb; z += max(ca, max(cb, cc)) - cc; if(f) printf("%d %d %d\n", x, y, z); else printf("-1\n"); } return 0; }
1002
1003
1004
1005
1006
思路:出题人要让你做不出$k$道题,只能让你复习时间最短的$n-k+1$道题都做不出,但是如果我复习时间最短的$n-k+1$道题的时间和是$m+1$,
你复习时间最短的$n-k+1$道题就至少有一道可以做出,所以公式是$m+1+(k-1)*\left\lceil\frac{m+1}{n-k+1}\right\rceil$。
代码:
#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include<bits/stdc++.h> using namespace std; #define y1 y11 #define fi first #define se second #define pi acos(-1.0) #define LL long long //#define mp make_pair #define pb push_back #define ls rt<<1, l, m #define rs rt<<1|1, m+1, r #define ULL unsigned LL #define pll pair<LL, LL> #define pli pair<LL, int> #define pii pair<int, int> #define piii pair<pii, int> #define pdd pair<double, double> #define mem(a, b) memset(a, b, sizeof(a)) #define debug(x) cerr << #x << " = " << x << "\n"; #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); //head int T; LL n, m, k; int main() { scanf("%d", &T); while(T--) { scanf("%lld %lld %lld", &n, &m, &k); LL B; if((m+1)%(n-k+1)) B = (m+1)/(n-k+1)+1; else B = (m+1)/(n-k+1); printf("%lld\n", B*(k-1)+m+1); } return 0; }
1007
1008
思路:将一个格子看成一个点(可以一直往右走形成一个环),然后问题就转换成从原点到$(x, y),(x-1, y),(x, y+1),(x-1, y+1)$的最小花费。
这样转换后一个点往上下左右走一步的花费是$b$,斜着走一步的最小花费是$c=min(2*b, a)$。然后优先斜着走,再直着走,直着走的时候,
每次优先两步一起走(花费$min(2*c,2*b)$),最后走一步。
代码:
#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include<bits/stdc++.h> using namespace std; #define y1 y11 #define fi first #define se second #define pi acos(-1.0) #define LL long long //#define mp make_pair #define pb push_back #define ls rt<<1, l, m #define rs rt<<1|1, m+1, r #define ULL unsigned LL #define pll pair<LL, LL> #define pli pair<LL, int> #define pii pair<int, int> #define piii pair<pii, int> #define pdd pair<double, double> #define mem(a, b) memset(a, b, sizeof(a)) #define debug(x) cerr << #x << " = " << x << "\n"; #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); //head int T; LL a, b, x, y, c; inline LL cal(LL x, LL y) { x = abs(x), y = abs(y); LL d = min(x, y), ans = 0; x -= d; y -= d; ans += d*c; ans += x/2*min(2*c, 2*b) + (x%2?b:0); ans += y/2*min(2*c, 2*b) + (y%2?b:0); return ans; } int main() { scanf("%d", &T); while(T--) { scanf("%lld %lld %lld %lld", &a, &b, &x, &y); LL ans = 4e18; c = min(a, 2*b); ans = min(ans, cal(x, y)); ans = min(ans, cal(x-1, y)); ans = min(ans, cal(x-1, y+1)); ans = min(ans, cal(x, y+1)); printf("%lld\n", ans); } return 0; }
1009
1010
思路:贪心,对方的损失相当于你的获得,所以对于每种颜色,把自己的个数和对方的个数加起来,就是总的贡献,然后按贡献排序。
代码:
#include<bits/stdc++.h> using namespace std; const int maxn=1e5+10; int a[maxn]; int b[maxn]; unordered_map<int,int> mp,tf; unsigned long long k1, k2; unsigned long long rng() { unsigned long long k3 = k1, k4 = k2; k1 = k4; k3 ^= k3 << 23; k2 = k3 ^ k4 ^ (k3 >> 17) ^ (k4 >> 26); return k2 + k4; } bool cmp1(pair<int,int> pa,pair<int,int> pb){ return pa.first+pa.second>pb.first+pb.second; } pair<int,int> pa[maxn]; int main(){ int T; scanf("%d",&T); while(T--){ mp.clear(); tf.clear(); int n,m,p; int num1=0; int num2=0; scanf("%d %d %d",&n,&m,&p); if(p==1){ for(int i=1;i<=n;i++) scanf("%d",&a[i]); for(int i=1;i<=m;i++) scanf("%d",&b[i]); } else { int mod; scanf("%llu%llu%d", &k1, &k2, &mod); for (int i = 1; i <= n; ++i) a[i] = rng() % mod; scanf("%llu%llu%d", &k1, &k2, &mod); for (int i = 1; i <= m; ++i) b[i] = rng() % mod; } for(int i=1;i<=n;i++){ mp[a[i]]++; } for(int i=1;i<=m;i++){ tf[b[i]]++; } int tot=0; for(int i=1;i<=n;i++){ if(mp[a[i]] && tf[a[i]]){ pa[++tot].first=mp[a[i]]; pa[tot].second=tf[a[i]]; mp[a[i]]=0; tf[a[i]]=0; } else num1+=mp[a[i]],mp[a[i]]=0; } for(int i=1;i<=m;i++){ num2+=tf[b[i]]; tf[b[i]]=0; } sort(pa+1,pa+1+tot,cmp1); for(int i=1;i<=tot;i++){ if(i%2==1){ num1+=pa[i].first+pa[i].second; num2+=pa[i].second; } else { num1+=pa[i].first; num2+=pa[i].first+pa[i].second; } } if(num1>num2) printf("Cuber QQ\n"); else printf("Quber CC\n"); } }
1011
思路:推相邻两个之间转移的花费公式。
代码:
#include<bits/stdc++.h> #define ll long long using namespace std; const int mod=1e9+7; const int maxn=1e6+10; ll f[maxn]; ll num[maxn]; int quick(int x,int n){ int ans=1; while(n){ if(n&1)ans=1ll*ans*x%mod; x=1ll*x*x%mod; n=n/2; } return ans; } struct FastIO { static const int S = 4e6; int wpos; char wbuf[S]; FastIO() : wpos(0) {} inline int xchar() { static char buf[S]; static int len = 0, pos = 0; if (pos == len) pos = 0, len = fread(buf, 1, S, stdin); if (pos == len) exit(0); return buf[pos++]; } inline int xuint() { int c = xchar(), x = 0; while (c <= 32) c = xchar(); for (; \'0\' <= c && c <= \'9\'; c = xchar()) x = x * 10 + c - \'0\'; return x; } inline int xint() { int s = 1, c = xchar(), x = 0; while (c <= 32) c = xchar(); if (c == \'-\') s = -1, c = xchar(); for (; \'0\' <= c && c <= \'9\'; c = xchar()) x = x * 10 + c - \'0\'; return x * s; } inline void xstring(char *s) { int c = xchar(); while (c <= 32) c = xchar(); for (; c > 32; c = xchar()) * s++ = c; *s = 0; } inline void wchar(int x) { if (wpos == S) fwrite(wbuf, 1, S, stdout), wpos = 0; wbuf[wpos++] = x; } inline void wint(int x) { if (x < 0) wchar(\'-\'), x = -x; char s[24]; int n = 0; while (x || !n) s[n++] = \'0\' + x % 10, x /= 10; while (n--) wchar(s[n]); wchar(\'\n\'); } inline void wstring(const char *s) { while (*s) wchar(*s++); } ~FastIO() { if (wpos) fwrite(wbuf, 1, wpos, stdout), wpos = 0; } } io; int main(){ int T;T=io.xint(); while(T--){ int n,q; n=io.xint(); q=io.xint(); for(int i=1;i<=n;i++){ int l,r,x,a;// scanf("%d %d %d %d",&l,&r,&x,&a); l=io.xint(); r=io.xint(); x=io.xint(); a=io.xint(); int invr=quick(r,mod-2); int invl=quick(l,mod-2); //cout<<"-------"<<l<<" "<<r<<" "<<invl<<" "<<invr<<endl; f[i]=( 1ll*a+1ll*(r-l)*invr%mod*(num[i-1]-num[x-1]) )%mod*r%mod*invl; f[i]=f[i]%mod; num[i]=(num[i-1]+f[i])%mod; //cout<<f[i]<<endl; } while(q--){ int l,r; l=io.xint(); r=io.xint(); printf("%lld\n",((num[r-1]-num[l-1])%mod+mod)%mod); } } }
2019 Multi-University Training Contest 8
Solved | Pro.ID | Title |
1001 | Acesrc and Cube Hypernet | |
1002 | Acesrc and Girlfriend | |
1003 | Acesrc and Good Numbers | |
1004 | Acesrc and Hunting | |
1005 | Acesrc and String Theory | |
1006 | Acesrc and Travel | |
1007 | Andy and Data Structure | |
1008 | Andy and Maze | |
1009 | Calabash and Landlord | |
1010 | Quailty and CCPC | |
1011 | Roundgod and Milk Tea |
1001
1002
1003
队友补了
1004
思路:构造
代码:
#include<bits/stdc++.h> using namespace std; const int maxn=1e6+10; vector<pair<int,int> > vs; //map<pair<int,int>,int> mp; int main(){ int T; scanf("%d",&T); while(T--){ int n,m; scanf("%d %d",&n,&m); if(n==1 && m==1) { printf("YES\n"); printf("1 1\n"); } else if(n==1 || m==1) printf("NO\n"); else if(n==2 && m==2 ) printf("NO\n"); else { printf("YES\n"); vs.clear(); //mp.clear(); int flag=0; if(n>m) { swap(n,m); flag=1; } for(int i=1;i<=n;i+=2){ if(n%2==1 && i+2==n){ // cout<<"----"<<endl; int x=i; int y=1; while(y<=m){ if(m%2==1 && y+2==m){ vs.push_back({x,y}); vs.push_back({x+2,y+1}); vs.push_back({x+1,y+2}); vs.push_back({x,y+1}); vs.push_back({x+1,y}); vs.push_back({x+2,y+2}); vs.push_back({x,y+2}); vs.push_back({x+1,y+1}); vs.push_back({x+2,y}); break; } else { vs.push_back({x,y}); vs.push_back({x+1,y+1}); vs.push_back({x+2,y}); vs.push_back({x,y+1}); vs.push_back({x+1,y}); vs.push_back({x+2,y+1}); } y+=2; } break; } else { if(m==3){ int x=i; int y=1; vs.push_back({x,y}); vs.push_back({x+1,y+1}); vs.push_back({x,y+2}); vs.push_back({x+1,y}); vs.push_back({x,y+1}); vs.push_back({x+1,y+2}); } else if(m%2==0){ int x=i; int y=1; while(y<=m) {vs.push_back({x,y}); y+=2; } y-=2; x++; y++; // printf("%d %d\n",x,y); while(y>=1) { vs.push_back({x,y}); y-=2; } y+=2; x--; y+=2; while(y<=m) {vs.push_back({x,y}); y+=2; } y-=2; x++; y--; while(y>=1) { vs.push_back({x,y}); y-=2; } y+=2; x--; y++; vs.push_back({x,y}); } else { int x=i; int y=1; while(y<=m) { vs.push_back({x,y});y+=2; } y-=2; x++; y--; while(y>=1) { vs.push_back({x,y}); y-=2; } y+=2; x--; y+=2; while(y<=m) { vs.push_back({x,y}); y+=2; } y-=2; x++; y++; while(y>=1) { vs.push_back({x,y});y-=2; } y+=2; x--; y++; vs.push_back({x,y}); } } } /*int kkk=0; for(int i=0;i<vs.size();i++){ if(mp[vs[i]]) kkk=1; mp[vs[i]]++; } for(int i=1;i<vs.size();i++){ int x=(vs[i].first-vs[i-1].first)*(vs[i].first-vs[i-1].first); int y=(vs[i].second-vs[i-1].second)*(vs[i].second-vs[i-1].second); double z=sqrt(1.00*x+1.00*y); if(z<=1 || z>=3) kkk=1; }*/ if(flag){ for(int i=0;i<vs.size();i++){ printf("%d %d\n",vs[i].second,vs[i].first); } } else{ for(int i=0;i<vs.size();i++){ printf("%d %d\n",vs[i].first,vs[i].second); } } } } } [ Copy to Clipboard ] [ Save to File]
1005
1006
思路:树形dp
代码:
#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include<bits/stdc++.h> using namespace std; #define y1 y11 #define fi first #define se second #define pi acos(-1.0) #define LL long long //#define mp make_pair #define pb emplace_back #define ls rt<<1, l, m #define rs rt<<1|1, m+1, r #define ULL unsigned LL #define pll pair<LL, LL> #define pli pair<LL, int> #define pii pair<int, int> #define piii pair<pii, int> #define pdd pair<double, double> #define mem(a, b) memset(a, b, sizeof(a)) #define debug(x) cerr << #x << " = " << x << "\n"; #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); //head const int N = 1e5 + 5; const LL INF = 0x3f3f3f3f3f3f3f3f; vector<int> g[N]; int a[N], b[N], n, u, v, T; LL dp[N][2], d[N][2]; void dfs(int u, int o) { dp[u][1] = -INF; dp[u][0] = INF; for (int v : g[u]) { if(v != o) { dfs(v, u); dp[u][1] = max(dp[u][1], dp[v][0]+a[u]-b[u]); dp[u][0] = min(dp[u][0], dp[v][1]+a[u]-b[u]); } } if(dp[u][1] == -INF) dp[u][1] = a[u]-b[u]; if(dp[u][0] == INF) dp[u][0] = a[u]-b[u]; } void DFS(int u, int o) { LL mx1 = INF, mx2 = INF; int v1 = -1, v2 = -1; if(u == 1 && g[u].size() == 1) d[u][0] = d[u][1] = a[u]-b[u]; for (int v : g[u]) { if(v != o) { if(dp[v][1]+a[u]-b[u] < mx1) { mx2 = mx1; v2 = v1; mx1 = dp[v][1]+a[u]-b[u]; v1 = v; } else if(dp[v][1]+a[u]-b[u] == mx1 || dp[v][1]+a[u]-b[u] < mx2) { mx2 = dp[v][1]+a[u]-b[u]; v2 = v; } } } // if(u != 1) { if(d[u][0] < mx1) { mx2 = mx1; v2 = v1; mx1 = d[u][0]; v1 = -1; } else if(d[u][0] == mx1 || d[u][0] < mx2) { mx2 = d[u][0]; v2 = -1; } //} for (int v : g[u]) { if(v != o) { if(v == v1) d[v][1] = max(d[v][1], mx2+a[v]-b[v]); else d[v][1] = max(d[v][1], mx1+a[v]-b[v]); } } /// mx1 = -INF, mx2 = -INF; v1 = -1, v2 = -1; for (int v : g[u]) { if(v != o) { if(dp[v][0]+a[u]-b[u] > mx1) { mx2 = mx1; v2 = v1; mx1 = dp[v][0]+a[u]-b[u]; v1 = v; } else if(dp[v][0]+a[u]-b[u] == mx1 || dp[v][0]+a[u]-b[u] > mx2) { mx2 = dp[v][0]+a[u]-b[u]; v2 = v; } } } //if(u != 1) { if(d[u][1] > mx1) { mx2 = mx1; v2 = v1; mx1 = d[u][1]; v1 = -1; } else if(d[u][1] == mx1 || d[u][1] > mx2) { mx2 = d[u][1]; v2 = -1; } // } for (int v : g[u]) { if(v != o) { if(v == v1) d[v][0] = min(d[v][0], mx2+a[v]-b[v]); else d[v][0] = min(d[v][0], mx1+a[v]-b[v]); } } for (int v : g[u]) { if(v != o) { DFS(v, u); } } } int main() { scanf("%d", &T); while(T--) { scanf("%d", &n); for (int i = 1; i <= n; ++i) scanf("%d", &a[i]); for (int i = 1; i <= n; ++i) scanf("%d", &b[i]); for (int i = 1; i < n; ++i) { scanf("%d %d", &u, &v); g[u].pb(v); g[v].pb(u); } dfs(1, 1); for (int i = 1; i <= n; ++i) d[i][0] = INF, d[i][1] = -INF; DFS(1, 1); LL ans = -INF; for (int i = 1; i <= n; ++i) { if(i == 1) ans = max(ans, dp[i][0]); else if(g[i].size() == 1) ans = max(ans, d[i][0]); else ans = max(ans, min(dp[i][0], d[i][0])); //cout << i << " " << dp[i][0] << " " << d[i][0] << endl; } printf("%lld\n", ans); for (int i = 1; i <= n; ++i) g[i].clear(); } return 0; }
1007
1008
队友补了
1009
思路:坐标离散化+状压+搜索
代码:
#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include<bits/stdc++.h> using namespace std; #define y1 y11 #define fi first #define se second #define pi acos(-1.0) #define LL long long //#define mp make_pair #define pb emplace_back #define ls rt<<1, l, m #define rs rt<<1|1, m+1, r #define ULL unsigned LL #define pll pair<LL, LL> #define pli pair<LL, int> #define pii pair<int, int> #define piii pair<pii, int> #define pdd pair<double, double> #define mem(a, b) memset(a, b, sizeof(a)) #define debug(x) cerr << #x << " = " << x << "\n"; #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); //head int T, x1[5], y1[5], x2[5], y2[5]; vector<int> vx, vy; int c[10][10]; bool vis[10][10]; int dir[4][2] = {0, 1, 1, 0, 0, -1, -1, 0}; void dfs(int x, int y) { vis[x][y] = true; for (int j = 0; j < 4; ++j) { int xx = x + dir[j][0]; int yy = y + dir[j][1]; if(1 <= xx && xx < vx.size() && 1 <= yy && yy < vy.size() && !vis[xx][yy] && c[xx][yy] == c[x][y]) { dfs(xx, yy); } } } int main() { scanf("%d", &T); while(T--) { vx.clear(); vy.clear(); for (int i = 1; i <= 2; ++i) { scanf("%d %d %d %d", &x1[i], &y1[i], &x2[i], &y2[i]); vx.pb(x1[i]), vx.pb(x2[i]); vy.pb(y1[i]), vy.pb(y2[i]); } vx.pb(-1), vx.pb(1e9 + 7); vy.pb(-1), vy.pb(1e9 + 7); sort(vx.begin(), vx.end()); vx.erase(unique(vx.begin(), vx.end()), vx.end()); sort(vy.begin(), vy.end()); vy.erase(unique(vy.begin(), vy.end()), vy.end()); for (int i = 1; i < vx.size(); ++i) { for (int j = 1; j < vy.size(); ++j) { int x = vx[i-1], y = vy[j-1]; int xx = vx[i], yy = vy[j]; int st = 0; for (int k = 1; k <= 2; ++k) { if(x >= x1[k] && y >= y1[k] && xx <= x2[k] && yy <= y2[k]) st |= 1<<k; } c[i][j] = st; } } for (int i = 1; i <= 7; ++i) for (int j = 1; j <= 7; ++j) vis[i][j] = false; int ans = 0; for (int i = 1; i < vx.size(); ++i) { for (int j = 1; j < vy.size(); ++j) { if(!vis[i][j]) { dfs(i, j); ans++; // cout << i << " " << j << endl; } } } printf("%d\n", ans); } return 0; }
1010
思路:模拟
代码:
// #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 <unordered_map> // #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 unsigned long long ull; 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 = 998244353; 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 = 1e5+9; struct node{ char str[15]; int p, t; }a[maxn]; bool cmp(node a, node b) { if(a.p == b.p) { return a.t < b.t; } return a.p > b.p; } int main(){ int T; scanf("%d", &T); while(T--) { int n,d; scanf("%d%d", &n, &d); for(int i=1; i<=n; i++) { scanf("%s%d%d", a[i].str, &a[i].p, &a[i].t); } if(n * d % 10 == 5) { sort(a+1, a+1+n, cmp); int up = n * d / 10 + 1; printf("%s\n", a[up].str); } else puts("Quailty is very great"); } return 0; }
1011
思路:贪心
代码:
#include<bits/stdc++.h> using namespace std; const int maxn=1e6+10; int a[maxn]; int b[maxn]; int main(){ int T; scanf("%d",&T); while(T--){ int n; scanf("%d",&n); long long tot=0; for(int i=1;i<=n;i++) { scanf("%d %d",&a[i],&b[i]); tot+=b[i]; } long long ans=0; for(int i=1;i<=n;i++){ long long c=min(tot-max(1ll*0,1ll*b[i]-ans)-ans,1ll*a[i]); if(c>0) ans+=c; } printf("%lld\n",ans); } }
2019 Multi-University Training Contest 9
Solved | Pro.ID | Title |
1001 | Rikka with Quicksort | |
1002 | Rikka with Cake | |
1003 | Rikka with Mista | |
1004 | Rikka with Geometric Sequence | |
1005 | Rikka with Game | |
1006 | Rikka with Coin | |
1007 | Rikka with Travels | |
1008 | Rikka with Stable Marriage | |
1009 | Rikka with Traffic Light | |
1010 | Rikka with Defensive Line | |
1011 | Rikka with Segment Tree |
1001
1002
思路:切成的块等于交点个数加一。
代码:
#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 <unordered_map> // #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 unsigned long long ull; 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 = 998244353; 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 = 1e5+9; // vector<pii>node; struct node{ int x, y; int tp; } a[maxn]; vector<int>vec; inline int getid(int x) { return lower_bound(vec.begin(), vec.end(), x) - vec.begin(); } char op[5]; bool cmp(node a, node b){ return a. y > b.y; } struct Tree{ int N; int sum[maxn]; void init(int n) { N = n; for (int i = 0; i <= N; ++i) sum[i] = 0; } int lowbit(int x) { return x & (-x); } void update(int pos, int val) { while(pos <= N) { sum[pos] += val; pos += lowbit(pos); } } int query(int pos) { int res = 0; while(pos > 0) { res += sum[pos]; pos -= lowbit(pos); } return res; } } Le, Ri; int main(){ int T; scanf("%d", &T); while(T--) { int n,m,k; scanf("%d%d%d", &n, &m, &k); vec.clear(); vec.pb(0); vec.pb(n); for(int i=1; i<=k; i++) { int x, y; scanf("%d%d%s", &x, &y, op); a[i].x = x, a[i].y = y; if(op[0] == \'U\') a[i].tp = 0; else if(op[0] == \'L\') a[i].tp = 1; else if(op[0] == \'D\') a[i].tp = 2; else a[i].tp = 3; vec.pb(x); } sort(vec.begin(), vec.end()); vec.erase(unique(vec.begin(), vec.end()), vec.end()); sort(a+1, a+1+k, cmp); Le.init(getid(n)); Ri.init(getid(n)); ll sum = 0; for(int i=1; i<=k; i++) { if(a[i].tp == 2) continue; if(a[i].tp == 1) { Le.update(getid(a[i].x), 1); } else if(a[i].tp == 3) { Ri.update(getid(a[i].x), 1); } else { sum += Le.query(getid(n)) - Le.query(getid(a[i].x)); sum += Ri.query(getid(a[i].x)); } } Le.init(getid(n)); Ri.init(getid(n)); for(int i=k; i>=1; i--) { if(a[i].tp == 0) continue; if(a[i].tp == 1) { Le.update(getid(a[i].x), 1); } else if(a[i].tp == 3) { Ri.update(getid(a[i].x), 1); } else { sum += Le.query(getid(n)) - Le.query(getid(a[i].x)); sum += Ri.query(getid(a[i].x)); } } printf("%lld\n", sum + 1); } return 0; }
1003
思路:桶排序+双指针。
代码:
#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include<bits/stdc++.h> using namespace std; #define y1 y11 #define fi first #define se second #define pi acos(-1.0) #define LL long long #define ll long long //#define mp make_pair #define pb emplace_back #define ls rt<<1, l, m #define rs rt<<1|1, m+1, r #define ULL unsigned LL #define pll pair<LL, LL> #define pli pair<LL, int> #define pii pair<int, int> #define piii pair<pii, int> #define pdd pair<double, double> #define mem(a, b) memset(a, b, sizeof(a)) #define debug(x) cerr << #x << " = " << x << "\n"; #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); //head const int N = 55, M = 1.2e6 + 10; int a[N], T, n, p[10]; vector<int> vc[10], vv[10], t[10]; int pos[10], l[M], r[M]; int main() { p[0] = 1; for (int i = 1; i < 10; ++i) p[i] = p[i-1]*10; scanf("%d", &T); while(T--) { scanf("%d", &n); for (int i = 0; i < n; ++i) scanf("%d", &a[i]); int y = n/2, x = n-y; int upx = 1<<x, upy = 1<<y; for (int i = 0; i < upx; ++i) { int tot = 0; for (int j = 0; j < x; ++j) if(i&(1<<j)) tot += a[j]; vc[0].pb(tot); } for (int i = 0; i < upy; ++i) { int tot = 0; for (int j = 0; j < y; ++j) if(i&(1<<j)) tot += a[j+x]; vv[0].pb(tot); } for (int i = 1; i <= 9; ++i) { for (int x : vc[i-1]) t[x/p[i-1]%10].pb(x); for (int j = 0; j < 10; ++j) { for (int x : t[j]) vc[i].pb(x); t[j].clear(); } } for (int i = 1; i <= 9; ++i) for (int &x : vc[i]) x %= p[i]; for (int i = 1; i <= 9; ++i) { for (int x : vv[i-1]) t[x/p[i-1]%10].pb(x); for (int j = 0; j < 10; ++j) { for (int x : t[j]) vv[i].pb(x); t[j].clear(); } } for (int i = 1; i <= 9; ++i) for (int &x : vv[i]) x %= p[i]; LL ans = 0; for (int i = 1; i < 10; ++i) { int p1 = 0, sz = upy, L = 4*p[i-1], R = 5*p[i-1]-1; int j = upx-1; for (; j >= 0; --j) { int x = vc[i][j]; if(x <= R) break; while(p1 < sz && vv[i][p1]+x <= p[i] + R) ++p1; r[j] = p1; } p1 = 0; for (; j >= 0; --j) { int x = vc[i][j]; while(p1 < sz && vv[i][p1]+x <= R) ++p1; r[j] = p1; } p1 = 0; j = upx-1; for (; j >= 0; --j) { int x = vc[i][j]; if(x < L) break; while(p1 < sz && vv[i][p1]+x < p[i] + L) ++p1; l[j] = p1; } p1 = 0; for (; j >= 0; --j) { int x = vc[i][j]; while(p1 < sz && vv[i][p1]+x < L) ++p1; l[j] = p1; } for (int j = 0; j < upx; ++j) { if(l[j] <= r[j]) ans += r[j]-l[j]; else ans += sz+r[j]-l[j]; } } printf("%lld\n", ans); for (int i = 0; i < 10; ++i) vc[i].clear(), vv[i].clear(); } return 0;
1004
1005
思路:特判$"z*"$,$"yyyyz*"$这两种情况,将z改成b
代码:
#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include<bits/stdc++.h> using namespace std; #define double long double #define y1 y11 #define fi first #define se second #define pi acos(-1.0) #define LL long long //#define mp make_pair #define pb emplace_back #define ls rt<<1, l, m #define rs rt<<1|1, m+1, r #define ULL unsigned LL #define pll pair<LL, LL> #define pli pair<LL, int> #define pii pair<int, int> #define piii pair<pii, int> #define pdd pair<double, double> #define mem(a, b) memset(a, b, sizeof(a)) #define debug(x) cerr << #x << " = " << x << "\n"; #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); //head int T; string s; int main() { fio; cin >> T; while(T--) { cin >> s; if(s[0] == \'z\') s[0] = \'b\'; else { for (int j = 0; j < s.size(); ++j) { if(s[j] != \'y\') { if(s[j] == \'z\') s[j] = \'b\'; break; } } } cout << s << endl; } return 0; }
1006
思路:我们发现10的个数不会超过2,20的个数不会超过10,50的个数不会超过2。然后预处理对于这三个硬币不同的个数能组成的面值,最后暴力判断100所需的个数。
代码:
#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include<bits/stdc++.h> using namespace std; #define double long double #define y1 y11 #define fi first #define se second #define pi acos(-1.0) #define LL long long //#define mp make_pair #define pb emplace_back #define ls rt<<1, l, m #define rs rt<<1|1, m+1, r #define ULL unsigned LL #define pll pair<LL, LL> #define pli pair<LL, int> #define pii pair<int, int> #define piii pair<pii, int> #define pdd pair<double, double> #define mem(a, b) memset(a, b, sizeof(a)) #define debug(x) cerr << #x << " = " << x << "\n"; #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); //head const int N = 105; int T, n, a[N]; vector<int> vc[3][11][3]; int main() { scanf("%d", &T); for (int i = 0; i <= 2; ++i) { for (int j = 0; j <= 10; ++j) { for (int k = 0; k <= 2; ++k) { for (int ii = 0; ii <= i; ++ii) { for (int jj = 0; jj <= j; ++jj) { for (int kk = 0; kk <= k; ++kk) { vc[i][j][k].pb(ii*10+jj*20+kk*50); } } } sort(vc[i][j][k].begin(), vc[i][j][k].end()); } } } while(T--) { scanf("%d", &n); bool f = false; for (int i = 1; i <= n; ++i) { scanf("%d", &a[i]); if(a[i]%10) f = true; } if(f) { printf("-1\n"); continue; } int ans = 1e9 + 10; for (int i = 0; i <= 2; ++i) { for (int j = 0; j <= 10; ++j) { for (int k = 0; k <= 2; ++k) { bool ok = true; int mx = 0; for (int l = 1; l <= n; ++l) { int t = min(a[l], a[l]%100+300); bool f = false; for (; t >= 0; t -= 100) { auto tt = lower_bound(vc[i][j][k].begin(), vc[i][j][k].end(), t); if(tt != vc[i][j][k].end() && (*tt) == t) { f = true; mx = max(mx, (a[l]-t)/100); break; } } if(!f) { ok = false; break; } } if(!ok) continue; ans = min(ans, i+j+k+mx); } } } printf("%d\n", ans); } return 0; }
1007
思路:直径上的端点一定会被用到,先把直径扣出来,然后在直径上求个前缀最大值和后缀最大值,在求出以直径上每个点为根的小树的中最长链。
代码:
#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 <unordered_map> // #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 unsigned long long ull; 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 = 998244353; 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 = 1e5+9; int n; vector<int>mp[maxn]; int vis[maxn]; int dis[maxn]; vector<int>lian; ///扣出最长链 void koulian() { for(int i=1; i<=n; i++) dis[i] = inf; dis[1] = 0; queue<int>que; que.push(1); int t = 1; while(!que.empty()) { int u = que.front(); que.pop(); if(dis[u] > dis[t])t = u; for(int v : mp[u]) { if(dis[v] > dis[u] + 1) { dis[v] = dis[u] + 1; que.push(v); } } } for(int i=1; i<=n; i++) dis[i] = inf; dis[t] = 0; que.push(t); int s = t; while(!que.empty()) { int u = que.front(); que.pop(); if(dis[u] > dis[s])s = u; for(int v:mp[u]) { if(dis[v] > dis[u] + 1) { dis[v] = dis[u] + 1; que.push(v); } } } lian.pb(s); vis[s] = 1; while(s != t) { for(int v : mp[s]) { if(dis[v] +1 == dis[s]) { s = v; lian.pb(s); vis[s] = 1; break; } } } } int dpa[maxn], dpb[maxn][2], pre[maxn]; int dppre[maxn], dpback[maxn]; ///求出以最长链上一个点为根节点的不经过最长链的最大深度 void dfs1(int u, int fa) { dpa[u] = 1; for(int v : mp[u]) { if(v == fa || vis[v]) continue; dfs1(v, u); dpa[u] = max(dpa[u], dpa[v] + 1); }} void dfs2(int u, int fa) { dpb[u][0] = dpb[u][1] = 1; ///dpb[0]表示包含根节点的最长链 ///dpb[1]表示包含根节点的次长链 pre[u] = 1; for(int v : mp[u]) { if(vis[v] || v == fa) continue; dfs2(v, u); pre[u] = max(pre[u], pre[v]); if(dpb[u][1] <= dpb[v][0] + 1){ dpb[u][1] = dpb[v][0] + 1; if(dpb[u][0] < dpb[u][1]) { swap(dpb[u][0], dpb[u][1]); } } } pre[u] = max(pre[u], dpb[u][0] + dpb[u][1] - 1); } int hei[maxn]; int main(){ int T; scanf("%d", &T); while(T--){ scanf("%d", &n); for(int i=1; i<n; i++) { int u, v; scanf("%d%d", &u, &v); mp[u].pb(v); mp[v].pb(u); } for(int i=0; i<=n; i++) vis[i] = 0, hei[i] = 0, pre[i] = 0, dppre[i] = 0,dpback[i] = 0; koulian(); for(int i=0; i<lian.size(); i++) { int v = lian[i]; dfs1(v, v); if(i)dppre[i] = max(dppre[i-1], dpa[v] + i); else dppre[i] = dpa[v]; for(int p : mp[v]) { if(vis[p]) continue; dfs2(p, p); pre[v] = max(pre[v], pre[p]); } pre[v] = max(pre[v], pre[lian[max(0, i-1)]]); } int cc = 0; for(int i=lian.size()-1; i>=0; i--) { if(i == lian.size() - 1) dpback[i] = dpa[lian[i]]; else dpback[i] = max(dpback[i+1], dpa[lian[i]] + cc); cc++; } int all = lian.size(); hei[all] = pre[lian[all-1]]; hei[pre[lian[all-1]]] = all; for(int i=lian.size() - 1; i>=1; i--) { int v = lian[i]; int a = dppre[i-1]; int b = dpback[i]; hei[a] = max(hei[a], b); hei[b] = max(hei[b], a); } ll sum = 0; int c = 0; for(int i=all; i>=1; i--) { c = max(c, hei[i]); sum = sum + c; } printf("%lld\n", sum); lian.clear(); for(int i=1; i<=n; i++) mp[i].clear(); } return 0; }
1008
思路:贪心,从最高位开始,每一位尽可能不同。
代码:
#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include<bits/stdc++.h> using namespace std; #define y1 y11 #define fi first #define se second #define pi acos(-1.0) #define LL long long //#define mp make_pair #define pb push_back #define ls rt<<1, l, m #define rs rt<<1|1, m+1, r #define ULL unsigned LL #define pll pair<LL, LL> #define pli pair<LL, int> #define pii pair<int, int> #define piii pair<pii, int> #define pdd pair<double, double> #define mem(a, b) memset(a, b, sizeof(a)) #define debug(x) cerr << #x << " = " << x << "\n"; #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); //head const int N = 1e5 + 5; int a[N], b[N], n, T; vector<int> vc; struct Trie { int trie[N*30][2], cnt[N*30], tot; inline void clr() { for (int i = 0; i <= tot; ++i) trie[i][0] = trie[i][1] = cnt[i] = 0; tot = 0; } inline void ins(int x) { int rt = 0; for (int i = 29; i >= 0; --i) { int id = (x>>i)&1; if(!trie[rt][id]) trie[rt][id] = ++tot; rt = trie[rt][id]; cnt[rt]++; } } }A, B; inline int solve() { int ra = 0, rb = 0, res = 0; for (int i = 29; i >= 0; --i) { if(A.cnt[A.trie[ra][0]] && B.cnt[B.trie[rb][1]]) { ra = A.trie[ra][0]; rb = B.trie[rb][1]; A.cnt[ra]--; B.cnt[rb]--; res |= 1<<i; } else if(A.cnt[A.trie[ra][1]] && B.cnt[B.trie[rb][0]]) { ra = A.trie[ra][1]; rb = B.trie[rb][0]; A.cnt[ra]--; B.cnt[rb]--; res |= 1<<i; } else if(A.cnt[A.trie[ra][0]] && B.cnt[B.trie[rb][0]]){ ra = A.trie[ra][0]; rb = B.trie[rb][0]; A.cnt[ra]--; B.cnt[rb]--; } else { ra = A.trie[ra][1]; rb = B.trie[rb][1]; A.cnt[ra]--; B.cnt[rb]--; } } return res; } int main() { scanf("%d", &T); while(T--) { scanf("%d", &n); A.clr(), B.clr(); for (int i = 1; i <= n; ++i) scanf("%d", &a[i]), A.ins(a[i]); for (int i = 1; i <= n; ++i) scanf("%d", &b[i]), B.ins(b[i]); LL ans = 0; for (int i = 1; i <= n; ++i) ans += solve(); printf("%lld\n", ans); } return 0; }
1009
1010
1011
2019 Multi-University Training Contest 10
Solved | Pro.ID | Title |
1001 | Minimum Spanning Trees | |
1002 | Line Graphs | |
1003 | Valentine\'s Day | |
1004 | Play Games with Rounddog | |
1005 | Welcome Party | |
1006 | Dense Subgraph | |
1007 | Closest Pair of Segments | |
1008 | Coins | |
1009 | Block Breaker | |
1010 | Domino Covering | |
1011 | Make Rounddog Happy |
1001
1002
1003
思路:如果有一个大于0.5,那么答案就是最大值,否则就是最大的几个合并的概率,这个可以暴力算。
代码:
#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include<bits/stdc++.h> using namespace std; #define y1 y11 #define fi first #define se second #define pi acos(-1.0) #define LL long long #define ll long long //#define mp make_pair #define pb emplace_back #define ls rt<<1, l, m #define rs rt<<1|1, m+1, r #define ULL unsigned LL #define pll pair<LL, LL> #define pli pair<LL, int> #define pii pair<int, int> #define piii pair<pii, int> #define pdd pair<double, double> #define mem(a, b) memset(a, b, sizeof(a)) #define debug(x) cerr << #x << " = " << x << "\n"; #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); //head const int N = 1e4 + 10; int T, n, a[N]; char s[15]; int main() { scanf("%d", &T); while(T--) { scanf("%d", &n); for (int i = 1; i <= n; ++i) { scanf("%s", s); a[i] = 0; for (int j = 0; j < 8; ++j) { if(s[j] == \'.\') continue; a[i] = a[i]*10+s[j]-\'0\'; } } sort(a+1, a+1+n); double ans; if(a[n] >= 500000) { ans = a[n]*1./1000000.; } else { ans = a[n]*1./1000000.; double tmp = ans, p = (1000000.-a[n])/1000000.; for (int i = n-1; i >= 1; --i) { tmp = (tmp*(1000000.-a[i]) + a[i]*p)/1000000.; p *= (1000000.-a[i])/1000000.; ans = max(ans, tmp); } } printf("%.10f\n", ans); } return 0; }
1004
1005
思路:队友写的
代码:
// #pragma GCC optimize(2) // #pragma GCC optimize(3) // #pragma GCC optimize(4) #include <bits/stdc++.h> // #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 = 998244353; 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 = 1e5+9; pll a[maxn]; multiset<ll>st; bool cmp(pll a, pll b) { if(a.fi == b.fi) { return a.se < b.se; } return a.fi > b.fi; } int main(){ int T; scanf("%d", &T); while(T--) { st.clear(); int n; scanf("%d", &n); for(int i=1; i<=n; i++) { scanf("%lld%lld", &a[i].fi, &a[i].se); } sort( a+1, a+1+n, cmp); ll premax = -inff; ll ans = inff; for(int i=n; i>=1; i--) st.insert(a[i].se); for(int i=1; i<=n; i++) { st.erase(st.find(a[i].se)); ans = min(ans, abs(premax - a[i].fi)); // if(premax < a[i].fi) { auto it = st.lower_bound(a[i].fi); if(it != st.end() && (*it )> premax) { ans = min(ans, abs(*it - a[i].fi)); } if(it != st.begin()) { it--; if((*it > premax)) { ans = min(ans, abs(*it - a[i].fi)); } } // } premax = max(premax, a[i].se); } printf("%lld\n", ans); } return 0; }
1006
1007
思路:先按x坐标排序,然后$O(n^2)$暴力枚举,再剪一下枝。
代码:
#include<bits/stdc++.h> using namespace std; const int maxn=10000+10; const double pi=acos(-1); struct Point{ double x,y; Point(){ x=0,y=0; } Point(double _x,double _y):x(_x),y(_y){} Point operator -(const Point &b)const { return Point(x-b.x,y-b.y);} }; double dis(Point A,Point B) { return sqrt( (A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y));} inline double cross(Point a,Point b) { return a.x*b.y-a.y*b.x; } //叉积 inline double dot(Point a,Point b) { return a.x*b.x+a.y*b.y; } //点积 struct node{ Point a,b,c; }pa[maxn]; bool up(node pa,node pb){ if(pa.c.x==pb.c.x) return pa.c.y<pb.c.y; return pa.c.x<pb.c.x; } double make(Point a,Point b,Point c){ double ans=1e18; double area=cross(a-c,b-c)/dis(a,b); area=fabs(area); //cout<<area<<endl; if(dot(a-b,c-b)<0) return ans; if(dot(b-a,c-a)<0) return ans; return area; } double work(node pa,node pb){ double ans=1e18; ans=min(ans,dis(pa.a,pb.a)); ans=min(ans,dis(pa.a,pb.b)); ans=min(ans,dis(pa.b,pb.a)); ans=min(ans,dis(pa.b,pb.b)); ans=min(ans,make(pa.a,pa.b,pb.a)); ans=min(ans,make(pa.a,pa.b,pb.b)); ans=min(ans,make(pb.a,pb.b,pa.a)); ans=min(ans,make(pb.a,pb.b,pa.b)); return ans; } int main(){ // cout<<dot(Point{1,1},Point{-1,0})<<endl; int T; scanf("%d",&T); while(T--){ int n; scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%lf %lf %lf %lf",&pa[i].a.x,&pa[i].a.y,&pa[i].b.x,&pa[i].b.y); pa[i].c.x=min(pa[i].a.x,pa[i].b.x); pa[i].c.y=min(pa[i].a.y,pa[i].b.y); } sort(pa+1,pa+1+n,up); double ans=1e18; for(int i=1;i<=n;i++){ double r=max(pa[i].a.x,pa[i].b.x); for(int j=i+1;j<=n;j++){ double l=min(pa[j].a.x,pa[j].b.x); if(l-r>ans) break; ans=min(ans,work(pa[i],pa[j])); } } printf("%.10f\n",ans); } }
1008
1009
思路:队友写的
代码:
// #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 = 998244353; 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 = 2009; int mp[maxn][maxn]; queue<pii>que; int nx[4][2] ={{0, 1}, {1, 0}, {-1, 0}, {0, -1}}; int main(){ int T; scanf("%d", &T); while(T--) { int n,m,q; scanf("%d%d%d", &n, &m, &q); for(int i=0; i<=n+1; i++) { for(int j=0; j<=m+1; j++) { mp[i][j] = 1; } } while(q--) { int x, y; int cnt = 0; scanf("%d%d", &x, &y); if(mp[x][y] == 0) puts("0"); else { while(!que.empty()) que.pop(); cnt = 1; mp[x][y] = 0; que.push(pii(x, y)); while(!que.empty()) { pii f = que.front(); que.pop(); int cx = f.fi, cy = f.se; for(int i=0; i<4; i++) { int tx = cx + nx[i][0]; int ty = cy + nx[i][1]; if(tx < 1 || tx > n || ty < 1 || ty > m) continue; if(mp[tx][ty] == 0) continue; if(mp[tx-1][ty] == 0 || mp[tx+1][ty] == 0) { if(mp[tx][ty-1] == 0||mp[tx][ty+1] == 0) { cnt++; mp[tx][ty] = 0; que.push(pii(tx, ty)); } } } } printf("%d\n", cnt); } } } return 0; }
1010
1011
思路:用单调栈求出以每个位置为最大值区间的左端点和右端点。由于还要保证每个数只出现一次,所以还要处理出每个位置往左往右不重复能到达的位置。最后再用启发式暴力枚举。
代码:
#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include<bits/stdc++.h> using namespace std; #define y1 y11 #define fi first #define se second #define pi acos(-1.0) #define LL long long #define ll long long //#define mp make_pair #define pb emplace_back #define ls rt<<1, l, m #define rs rt<<1|1, m+1, r #define ULL unsigned LL #define pll pair<LL, LL> #define pli pair<LL, int> #define pii pair<int, int> #define piii pair<pii, int> #define pdd pair<double, double> #define mem(a, b) memset(a, b, sizeof(a)) #define debug(x) cerr << #x << " = " << x << "\n"; #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); //head const int N = 3e5 + 5; int a[N], n, k, T, L[N], R[N], p[N], nxt[N], pre[N], mx[N], mn[N]; stack<int> st; int main() { scanf("%d", &T); while(T--) { scanf("%d %d", &n, &k); for (int i = 1; i <= n; ++i) scanf("%d", &a[i]); a[0] = a[n+1] = n+1; while(!st.empty()) st.pop(); st.push(0); for (int i = 1; i <= n; ++i) { while(!st.empty() && a[st.top()] <= a[i]) st.pop(); L[i] = st.top()+1; st.push(i); } while(!st.empty()) st.pop(); st.push(n+1); for (int i = n; i >= 1; --i) { while(!st.empty() && a[st.top()] <= a[i]) st.pop(); R[i] = st.top()-1; st.push(i); } for (int i = 1; i <= n; ++i) p[i] = n+1; for (int i = n; i >= 1; --i) { nxt[i] = p[a[i]]; p[a[i]] = i; } for (int i = 1; i <= n; ++i) p[i] = 0; for (int i = 1; i <= n; ++i) { pre[i] = p[a[i]]; p[a[i]] = i; } mx[n] = n; for (int i = n-1; i >= 1; --i) { mx[i] = min(mx[i+1], nxt[i]-1); } mn[1] = 1; for (int i = 2; i <= n; ++i) { mn[i] = max(mn[i-1], pre[i]+1); } LL ans = 0; for (int i = 1; i <= n; ++i) { int len = max(1, a[i]-k); if(i-L[i] <= R[i]-i) { for (int j = L[i]; j <= i; ++j) { int r = min(R[i], mx[j]); if(r >= i && r-j+1 >= len) { ans += min(r-j+1-len+1, r-i+1); } } } else { for (int j = i; j <= R[i]; ++j) { int l = max(L[i], mn[j]); if(l <= i && j-l+1 >= len) { ans += min(j-l+1-len+1, i-l+1); } } } } printf("%lld\n", ans); } return 0; }