A.Equivalent+Prefixes
思路:
二分答案,然后运用单调栈求出右边第一个比它小的数,若对于每一个二分答案左边的每一个数右边第一个比它小的数位置必须相同。
1 #include<bits/stdc++.h> 2 3 using namespace std; 4 5 const int N=200000; 6 int s[N],tot,a[N],b[N],f1[N],c[N],d[N],f2[N],n; 7 bool check(int x) 8 { 9 for (int i=1; i<=x; i++) 10 { 11 if (f1[i]!=f2[i]) 12 { 13 return 0; 14 } 15 } 16 return 1; 17 } 18 19 void work(int a[],int f[],int d[],int n) 20 { 21 tot=0; 22 for (int i=n; i>=1; i--) 23 { 24 while (tot>0&&s[tot]>a[i]) 25 { 26 tot--; 27 } 28 s[++tot]=a[i]; 29 if (tot>1) 30 { 31 f[i]=d[s[tot-1]]; 32 } 33 else 34 { 35 f[i]=-1; 36 } 37 } 38 } 39 40 int main() 41 { 42 while(~scanf("%d",&n)) 43 { 44 for (int i=1; i<=n; i++) 45 { 46 scanf("%d",&a[i]); 47 c[a[i]]=i; 48 } 49 for (int i=1; i<=n; i++) 50 { 51 scanf("%d",&b[i]); 52 d[b[i]]=i; 53 } 54 int l=1,r=n,ans=1; 55 while (l<=r) 56 { 57 int mid=(l+r)>>1; 58 work(a,f1,c,mid); 59 work(b,f2,d,mid); 60 if (check(mid)) 61 { 62 l=mid+1; 63 ans=mid; 64 } 65 else 66 { 67 r=mid-1; 68 } 69 } 70 printf("%d ",ans); 71 } 72 }
J.Fraction Comparision
不用说了,太简单了
1 #include <bits/stdc++.h> 2 3 using namespace std; 4 typedef long long ll; 5 ll x, y, a, b; 6 7 int main() { 8 while(scanf("%lld%lld%lld%lld", &x, &y, &a ,&b) == 4) { 9 __int128 tmp1 = 1, tmp2 = 1; 10 tmp1 = tmp1 * x * b; 11 tmp2 = tmp2 * y * a; 12 if(tmp1 == tmp2) puts("="); 13 else if(tmp1 < tmp2) puts("<"); 14 else puts(">"); 15 } 16 return 0; 17 }
F.Random Point in Triangle
1 #include<bits/stdc++.h> 2 using namespace std; 3 long long ans,vecx1,vecx2,vecy1,vecy2,x1,x2,x3,yy,y2,y3; 4 int main() 5 { 6 while (~scanf("%lld%lld%lld%lld%lld%lld",&x1,&yy,&x2,&y2,&x3,&y3)) 7 { 8 vecx1=x2-x1; 9 vecy1=y2-yy; 10 vecx2=x3-x1; 11 vecy2=y3-yy; 12 ans=11*abs(vecx1*vecy2-vecy1*vecx2); 13 cout<<ans<<endl; 14 } 15 }
B.Integration
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int N=2000; 5 const ll p=1e9+7; 6 ll pow1(ll a,ll b) { 7 ll res = 1; 8 while (b) { 9 if (b & 1) { 10 res = res * a % p; 11 } 12 b >>= 1; 13 a = a * a % p; 14 } 15 return res; 16 } 17 18 ll inv(ll x) { 19 return pow1(x, p - 2); 20 } 21 22 ll k,n,a[N],c[N],ans,ret; 23 int main(){ 24 k=inv(2); 25 while (~scanf("%lld",&n)){ 26 ans=0; 27 for (int i=1;i<=n;i++){ 28 scanf("%lld",&a[i]); 29 } 30 for (int i=1;i<=n;i++){ 31 ret=1; 32 for (int j=1;j<=n;j++){ 33 if (i==j) continue; 34 ret=ret*(a[j]*a[j]%p-a[i]*a[i]%p+p)%p; 35 } 36 c[i]=inv(ret); 37 } 38 for (int i=1;i<=n;i++){ 39 ans=(ans+c[i]*k%p*inv(a[i]))%p; 40 } 41 printf("%lld ",ans); 42 } 43 }
E.ABBA
思路
思考这样一个问题:给你一个长为2*(n+m)的字符串,判断它是否能分解出n个’AB’和m个’BA‘。
贪心的思想,我们从前往后扫一遍,遇到A,如果还有’AB’没分到’A’,就把这个’A’分给’AB‘,否则看看’BA’种是否有分到了’B’但还没有分到’A’的,如果有,就把这个’A’分给他,如果没有,那么这个’A’就无法和任何东西配,这个字符串就不满足条件。
有了分配’A’和’B’的原则之后,我们就可以开始dp了。dp[i][j]表示放了i个’A’,j个’B’后依然有可能满足条件的方案数。
dp[i][j]的转移:
考虑放‘A’:
如果当前已经放的‘A’的个数比需要的’AB’个数少,可以直接放
如果当前已经放的’A’的个数大于等于n了,看看放了多少个‘B’,如果放的’B‘的个数小于多出来的’A’,可以直接放。
所以 dp[i+1][j] += dp[i][j] (i < n + j)
'B’同理。
这题的关键是要先想好怎么去分配A和B的归属,然后再去想dp。
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int N=2002; 5 const ll p=1e9+7; 6 ll n,m,f[N][N]; 7 int main() { 8 while (~scanf("%lld%lld", &n, &m)) { 9 for (int i = 0; i <= n + m; i++) { 10 for (int j = 0; j <= n + m; j++) { 11 f[i][j] = 0; 12 } 13 } 14 f[0][0] = 1; 15 for (int i = 0; i <= n + m; i++) { 16 for (int j = 0; j <= n + m; j++) { 17 if (i < n + j) f[i + 1][j] = (f[i + 1][j] + f[i][j]) % p; 18 if (j < m + i) f[i][j + 1] = (f[i][j + 1] + f[i][j]) % p; 19 } 20 } 21 printf("%lld ", f[n + m][n + m]); 22 } 23 }
c.Euclidean Distance
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int N=10010; 5 ll n,m,a[N],now,sum[N],ansa,ansb; 6 int main() { 7 while (~scanf("%lld%lld", &n, &m)) { 8 now = n; 9 for (int i = 1; i <= n; i++) { 10 scanf("%lld", &a[i]); 11 } 12 sort(a + 1, a + n + 1, greater<int>()); 13 sum[0] = -m; 14 for (int i = 1; i <= n; i++) { 15 sum[i] = sum[i - 1] + a[i]; 16 } 17 for (int i = 1; i < n; i++) { 18 if (sum[i] > a[i + 1] * i) { 19 now = i; 20 break; 21 } 22 } 23 ansa = sum[now] * sum[now] * now; 24 ansb = now * now; 25 for (ll i = now + 1; i <= n; i++) { 26 ansa += a[i] * a[i] * ansb; 27 } 28 ansb *= m * m; 29 ll d = __gcd(ansa, ansb); 30 ansa /= d; 31 ansb /= d; 32 if (ansb == 1 || ansa == 0) { 33 printf("%lld ", ansa); 34 } else { 35 printf("%lld/%lld ", ansa, ansb); 36 } 37 } 38 } 39
H.XOR
I.Points Division
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 typedef long long LL; 5 const LL N = 100010; 6 const LL M = 999999999999999999LL; 7 8 LL n, num; 9 LL p[N]; 10 map<LL, LL>m; 11 12 LL lazy[N << 2]; 13 struct Node { 14 LL l, r, v; 15 } t[N << 2]; 16 17 struct Data { 18 LL x, y, a, b; 19 } w[N]; 20 21 inline bool cmp(Data a, Data b) 22 { 23 if (a.x == b.x) return a.y > b.y; 24 return a.x < b.x; 25 } 26 27 inline void pushdown(LL x) 28 { 29 t[x << 1].v += lazy[x]; 30 t[x << 1 | 1].v += lazy[x]; 31 lazy[x << 1] += lazy[x]; 32 lazy[x << 1 | 1] += lazy[x]; 33 lazy[x] = 0; 34 } 35 36 void buildtree(LL x, LL l, LL r) 37 { 38 t[x].l = l, t[x].r = r, t[x].v = -M, lazy[x] = 0; 39 if (l == r) return; 40 register int mid = (l + r) >> 1; 41 buildtree(x << 1, l, mid), buildtree(x << 1 | 1, mid + 1, r); 42 } 43 44 void change(LL x, LL l, LL r, LL z) 45 { 46 if (t[x].l == l && t[x].r == r) { 47 t[x].v += z, lazy[x] += z; 48 return; 49 } 50 if (lazy[x]) pushdown(x); 51 register LL mid = (t[x].l + t[x].r) >> 1; 52 if (r <= mid) change(x << 1, l, r, z); 53 else if (l > mid) change(x << 1 | 1, l, r, z); 54 else change(x << 1, l, mid, z), change(x << 1 | 1, mid + 1, r, z); 55 t[x].v = max(t[x << 1].v, t[x << 1 | 1].v); 56 } 57 58 void change(LL x, LL pos, LL z) 59 { 60 if (t[x].l == t[x].r) { 61 t[x].v = max(t[x].v, z); 62 return; 63 } 64 if (lazy[x]) pushdown(x); 65 register LL mid = (t[x].l + t[x].r) >> 1; 66 if (pos <= mid) change(x << 1, pos, z); 67 else change(x << 1 | 1, pos, z); 68 t[x].v = max(t[x << 1].v, t[x << 1 | 1].v); 69 } 70 71 LL query(LL x, LL l, LL r) 72 { 73 if (t[x].l == l && t[x].r == r) return t[x].v; 74 if (lazy[x]) pushdown(x); 75 register LL mid = (t[x].l + t[x].r) >> 1; 76 if (r <= mid) return query(x << 1, l, r); 77 else if (l > mid) return query(x << 1 | 1, l, r); 78 else return max(query(x << 1, l, mid), query(x << 1 | 1, mid + 1, r)); 79 } 80 81 int main() 82 { 83 while (scanf("%lld", &n) != EOF) { 84 num = 0; 85 for (register LL i = 1; i <= n; ++i) { 86 scanf("%lld %lld %lld %lld", &w[i].x, &w[i].y, &w[i].a, &w[i].b); 87 p[i] = w[i].y; 88 } 89 sort(p + 1, p + n + 1); 90 for (register LL i = 1; i <= n; ++i) { 91 if (p[i] != p[i - 1]) m[p[i]] = ++num; 92 } 93 for (register LL i = 1; i <= n; ++i) { 94 w[i].y = m[w[i].y]; 95 } 96 sort(w + 1, w + n + 1, cmp); 97 buildtree(1, 0, num); 98 change(1, 0, 0); 99 register LL z; 100 for (register LL i = 1; i <= n; ++i) { 101 z = query(1, 0, w[i].y); 102 change(1, w[i].y, z + w[i].b); 103 if (w[i].y != num) change(1, w[i].y + 1, num, w[i].b); 104 change(1, 0, w[i].y - 1, w[i].a); 105 } 106 printf("%lld ", t[1].v); 107 } 108 return 0; 109 }