K-King of range
题目大意:给我们一组数组,计算有多少个区间的(max-min)> k。本题我打算暴力,结果代码通过率为0···自闭了
解法:听说用st表和单调队列解决,看了一些大佬的代码发现貌似不难,比如l和r组成的区间合法,那么l向左同时r向右的区间均合法,这样可以省去不少时间
#include <bits/stdc++.h> using namespace std; const int N = 2e5 + 10; int a[N],q1[N],q2[N]; int n,m; long long query(int x){ int l1 = 1,r1 = 0,l2 = 1,r2 = 0; int l = 1; long long ans = 0; for(int i = 1;i <= n;i++){ while(l1 <= r1 && a[q1[r1]] <= a[i]) r1--; while(l2 <= r2 && a[q2[r2]] >= a[i]) r2--; q1[++r1] = i; q2[++r2] = i; while(l <= i && a[q1[l1]] - a[q2[l2]] > x){ ans += 1ll * (n - i + 1); l++; while(l1 <= r1 && q1[l1] <l) l1++; while(l2 <= r2 && q2[l2] <l) l2++; } } return ans; } int main() { cin >> n >> m; for(int i = 1;i <= n;i++) cin >> a[i]; while(m--){ int x; cin >> x; printf("%lld",query(x)); printf("\n"); } return 0; }
J.jewels
题目大意:你的坐标是( 0 , 0 , 0 ) (0,0,0)(0,0,0),有m个宝物,分别坐标是是( x i , y i , z i ) ,你每次获取一个宝物的费用是两者的距离的平方,每秒只能获取一个宝物,从第0 00秒开始,问获取所有宝物的最小费用
解法:看数据小估计用DP?或者DFS,时间复杂度O(n3)左右,三次的没试过所以这题放弃了,看了大佬的代码:
#include <bits/stdc++.h> using namespace std; typedef long long ll; const ll INF = 0x3f3f3f3f3f3f3f3f; const int N = 310; ll w[N][N]; ll la[N], lb[N]; bool va[N], vb[N]; int match[N]; int n; ll delta, upd[N]; ll p[N]; ll c[N]; int x[N], y[N], z[N], v[N]; void bfs(int x) { int a, y = 0, y1 = 0; for (int i = 1; i <= n; ++ i) p[i] = 0, c[i] = INF; match[y] = x; do { a = match[y], delta = INF, vb[y] = true; for (int b = 1; b <= n; ++ b) { if (!vb[b]) { if (c[b] > la[a] + lb[b] - w[a][b]) c[b] = la[a] + lb[b] - w[a][b], p[b] = y; if (c[b] < delta) //还是取最小的 delta = c[b], y1 = b; } } for (int b = 0; b <= n; ++ b) if (vb[b]) la[match[b]] -= delta, lb[b] += delta; else c[b] -= delta; y = y1; } while (match[y]); while (y)match[y] = match[p[y]], y = p[y]; } ll KM() { for (int i = 1; i <= n; ++ i) match[i] = la[i] = lb[i] = 0; for (int i = 1; i <= n; ++ i) { for (int j = 1; j <= n; ++ j) vb[j] = false; bfs(i); } ll res = 0; for (int y = 1; y <= n; ++ y) //若匹配失败w[match[y]][y]=INF; res += w[match[y]][y]; return res; } ll dis(int x, int y, int z) { return 1ll * x * x + 1ll * y * y + 1ll * z * z; } int main() { cin >> n; for (int i = 1; i <= n; i++) cin >>x[i] >> y[i] >> z[i] >> v[i]; for (int i = 1; i <= n; i++) for (int j = 1; j <= n; j++) w[i][j] = -1ll * dis(x[j], y[j], z[j] + (i - 1) * v[j]); printf("%lld\n",-1ll * KM()); return 0; }
上面的代码是参考了CSDN的匿枫大佬的
H.Holding Two
大意:构造01矩阵,使对角线、竖线、横线三个方向都不会出现三个相同的数字,如果不存在输出-1
题解:不可能不存在···构造00110011,下面岔开这种类型的就行,最简便的代码贴下面了,当然自己写的也可
#include <bits/stdc++.h> using namespace std; int a[2000][2000]={0},n,m; int col[4]={1,1,0,0}; int main(){ cin>>n>>m; for(int i=0;i<n;i++){ int t=col[i%4]; for (int j=0;j<m;j++){ a[i][j]=1-t; t=a[i][j]; } } for(int i=0;i<n;i++){ for (int j=0;j<m;j++){ cout<<a[i][j]; } cout<<endl; } }
CSDN某大佬看的,觉得很简洁就贴了,当然自己也写得出来(懒)
C.Cheating and Stealing(这种题不可能做得出来,写一下自己以后看看皮毛得了,这种过的人极少,代码这些全是贴的)
题意:
和打兵乓球差不多求题目要求的(自己看吧)
思路:
很显然,至少i 球分出胜负,所以枚举是调和级数O(nlogn),考虑如何O(1)预处理,事实上,我们发现只需要关注两边第i 次得分时候的情况和平局的情况,因为要么在此时决出胜负,要么一直平局到有人赢或无法决出胜负。那就预处理下前缀和和第i 个W/L的位置和在i次平局到什么时候可以分出胜负,就是个简单dp,分类讨论即可,具体来说就是
1.第i 次能赢吗
2.赢不了再加一个能赢吗
3.平局的话能赢吗
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn=1e6+5; const int mod=998244353; int sumW[maxn],sumL[maxn],cntW,cntL,posL[maxn],posW[maxn]; int equ[maxn],n; char s[maxn]; int main(){ cin>>n; cin>>(s+1); for(int i=1;i<=n;++i){ if(s[i]=='W'){ sumW[i]=sumW[i-1]+1; sumL[i]=sumL[i-1]; posW[++cntW]=i; }else{ sumW[i]=sumW[i-1]; sumL[i]=sumL[i-1]+1; posL[++cntL]=i; } } for(int i=n+1;i>=1;--i){ if(i>=n) equ[i]=n+1; else equ[i]=(s[i]==s[i+1])?i+1:equ[i+2]; } int ans=0,win; for(int i=1,num=1;i<=n;++i,num=(ll)num*(n+1)%mod){ win=0; for(int l=1,r;l<=n;l=r+1){ int nxtW=(cntW-sumW[l-1]>=i)?posW[sumW[l-1]+i]:n+1; int nxtL=(cntL-sumL[l-1]>=i)?posL[sumL[l-1]+i]:n+1; if(nxtW==n+1&&nxtL==n+1){//分不出 r=n; }else if(nxtW<nxtL){ if(i-(sumL[nxtW]-sumL[l-1])>=2)//第i个已经赢了 r=nxtW,win++; else if(nxtW==n)//分不出 r=n; else if(nxtW+1!=nxtL){//加一场就赢了 r=nxtW+1,win++; }else{ int pos=equ[nxtW+2]; if(pos==n+1)r=n; else r=pos,win+=(s[pos]=='W');//破平局 } }else{ if(i-(sumW[nxtL]-sumW[l-1])>=2) r=nxtL; else if(nxtL==n) r=n; else if(nxtL+1!=nxtW) r=nxtL+1; else{ int pos=equ[nxtL+2]; if(pos==n+1)r=n; else r=pos,win+=(s[pos]=='W'); } } } ans=(ans+(ll)win*num%mod)%mod; } cout<<ans; return 0; }
原文链接:https://blog.csdn.net/weixin_45539557/article/details/119301046