牛客练习赛50-记录
正題
比賽鏈接:https://ac.nowcoder.com/acm/contest/1080#question
成績
本屆
升高二屆
總結
以后還是不要寫太多自己不擅長的寫法,空間要多檢查,不要像個傻逼一樣啥都寫錯。
盡量不要為了省一點空間和時間寫一些不舒服的東西,盡量在能通過的情況下自己怎么舒服怎么來就好了。
T1:tokitsukazeandConnectionT1:tokitsukaze\ and\ ConnectionT1:tokitsukaze?and?Connection
題目大意
給出一個字符串,求里面的字母是不是都是連續的。
解題思路
暴力枚舉,開個桶存儲之前有沒有出現過。
codecodecode
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; int n; bool v[2333],flag; char s[1000]; int main() {scanf("%d%s",&n,s+1);for(int i=1;i<=n;i++){if(i==1||s[i]!=s[i-1]){if(v[s[i]]) {flag=1;break;}else v[s[i]]=1;}}if(flag) printf("NO");else printf("YES"); }T2:tokitsukazeandHashTableT2:tokitsukaze\ and\ Hash\ TableT2:tokitsukaze?and?Hash?Table
題目大意
將nnn個數字插入長度為nnn的哈希表,數值為x%nx\%nx%n,求最后hashhashhash表的狀態。
解題思路
考慮到暴力枚舉肯定會被卡成O(n2)O(n^2)O(n2),所以我們用樹狀數組+二分可以做到O(log?2n)O(\log^2n)O(log2n)找到下一個空位,若沒有空位我們就直接用最前方的空位即可。
codecodecode
#include<cstdio> #define lowbit(x) x&-x using namespace std; const int N=1100000; int n,op,v[N],t[N]; void add(int x,int val) {while(x<=n){t[x]+=val;x+=lowbit(x);} } int ask(int x) {int ans=0;while(x){ans+=t[x];x-=lowbit(x);}return ans; } int main() {scanf("%d",&n);op=1;for(int i=1;i<=n;i++){int X,x;scanf("%d",&X);x=X%n+1;int l=x,r=n,w=ask(x-1);while(l<=r){int mid=(l+r)/2;if(ask(mid)-w==mid-(x-1)) l=mid+1;else r=mid-1;}if(l<=n&&!v[l])v[l]=X+1,add(l,1);else{while(v[op])op++;v[op]=X+1;add(op,1);}}for(int i=1;i<=n;i++)printf("%d ",v[i]-1); }T3:tokitsukazeandSoldierT3:tokitsukaze\ and\ SoldierT3:tokitsukaze?and?Soldier
題目大意
若干個人,第iii個戰力為viv_ivi?,若這個人在團里要求不超過sis_isi?個人,選擇若干個人能組成的最大戰斗力。
解題思路
這個十分顯然的貪心題目,我們先按照sis_isi?從大到小排序,然后我們可以開始枚舉,我們發現我們枚舉到iii時人數不能超過sis_isi?個。我們可以維護一個優先隊列,每次sis_isi?縮小時我們就將價值最小的給彈出來就好了。
codecodecode
#include<cstdio> #include<cstring> #include<algorithm> #include<queue> #define ll long long using namespace std; const ll N=110000; priority_queue<ll> q; struct node{ll v,s; }a[N]; ll n,ans,maxs; bool cMp(node x,node y) {return x.s>y.s;} int main() {scanf("%lld",&n);for(ll i=1;i<=n;i++)scanf("%lld%lld",&a[i].v,&a[i].s);sort(a+1,a+1+n,cMp);for(ll i=1;i<=n;i++){while(q.size()>=a[i].s)ans+=q.top(),q.pop();q.push(-a[i].v);ans+=a[i].v;maxs=max(maxs,ans);}printf("%lld",maxs); }T4:tokitsukazeandEventT4:tokitsukaze\ and\ EventT4:tokitsukaze?and?Event
題目大意
一張無向圖,普通模式下邊權為aia_iai?,夜戰模式邊權為bib_ibi?。在難度kkk時可以在k~nk\sim nk~n中任意一個點轉換為夜戰模式,但不能轉回來。
求難度在1~n1\sim n1~n的情況下分別的最短路。
解題思路
我們設dis1idis1_idis1i?表示普通模式下s~is\sim is~i的最短路長度,dis2idis2_idis2i?表示夜戰模式下i~ti\sim ti~t的最短路。
對于難度為kkk答案顯然為min{dis1i+dis2i}(i≥k)min\{dis1_i+dis2_{i}\}(i\geq k)min{dis1i?+dis2i?}(i≥k)。我們倒著枚舉即可。
codecodecode
#include<cstdio> #include<cstring> #include<queue> #define ll long long using namespace std; const ll N=100010,M=200010; struct node{ll pos,dis;bool operator<(const node &x)const{return x.dis<dis;} }; struct edge_node{ll to,next,a,b; }a[M]; priority_queue<node> q; ll tot,ls[N],dis[N],dis2[N],n,m,s,t,f[N],ans; bool v[N]; void addl(ll x,ll y,ll A,ll b) {a[++tot].to=y;a[tot].next=ls[x];ls[x]=tot;a[tot].a=A;a[tot].b=b; } void dij(ll s) {dis[s]=0;q.push((node){s,0});while(!q.empty()){node tmp=q.top();q.pop();ll x=tmp.pos;if(v[x]) continue;v[x]=1;for(ll i=ls[x];i;i=a[i].next){ll y=a[i].to;if(dis[y]>dis[x]+a[i].a){dis[y]=dis[x]+a[i].a;if(!v[y])q.push(node{y,dis[y]});}}} } void dij2(ll s) {dis2[s]=0;memset(v,0,sizeof(v));q.push((node){s,0});while(!q.empty()){node tmp=q.top();q.pop();ll x=tmp.pos;if(v[x]) continue;v[x]=1;for(ll i=ls[x];i;i=a[i].next){ll y=a[i].to;if(dis2[y]>dis2[x]+a[i].b){dis2[y]=dis2[x]+a[i].b;if(!v[y])q.push(node{y,dis2[y]});}}} } int main() {scanf("%lld%lld",&n,&m);memset(dis2,127,sizeof(dis2));memset(dis,127,sizeof(dis));for(ll i=1;i<=m;i++){ll x,y,A,b;scanf("%lld%lld%lld%lld",&x,&y,&A,&b);addl(x,y,A,b);addl(y,x,A,b);}scanf("%lld%lld",&s,&t);dij(s);dij2(t);ans=1e18;for(ll i=n;i>=1;i--)ans=min(ans,dis[i]+dis2[i]),f[i]=ans;for(ll i=1;i<=n;i++)printf("%lld\n",f[i]); }T5:tokitsukazeandSegmentationT5:tokitsukaze\ and\ SegmentationT5:tokitsukaze?and?Segmentation
題目大意
給出一串數字,求將數字劃分要求
求劃分方案數。
解題思路
很顯然的數位dpdpdp
設fi,j,0/1f_{i,j,0/1}fi,j,0/1?表示到第iii為,當前劃分的數字之和為jjj,是不是純0構成的。
codecodecode
#include<cstdio> #include<cstring> #include<algorithm> #define ll long long using namespace std; const ll N=110000,XJQ=998244353; ll n,f[N][3][2]; char s[N]; int main() {scanf("%lld%s",&n,s+1);for(int i=1;i<=n;i++)s[i]-='0';f[1][s[1]%3][s[1]!=0]=1;for(ll i=1;i<=n;i++){(f[i][s[i]%3][s[i]!=0]+=f[i-1][0][0]+f[i-1][0][1])%=XJQ;for(ll j=0;j<3;j++)(f[i+1][(j+s[i+1])%3][1]+=f[i][j][1])%=XJQ;}printf("%lld",(f[n][0][0]+f[n][0][1])%XJQ); }總結
以上是生活随笔為你收集整理的牛客练习赛50-记录的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 360路由器怎么重新设置360路由器手机
- 下一篇: P3750-[六省联考2017]分手是祝