牛客算法週週練11 (A模擬,B 分組 染色,C 線段樹 區間求和,區間異或 ,D 思維 ,E 思維+差分)

題目鏈接

A-切題之路

做法:按照題意 模擬一下就好了,得用longlong

#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define ll long long
#define maxn 1005
#define inf 1e9
#define pb push_back
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define per(i,a,b) for(int i=a;i>=b;i--)
using namespace std;

inline ll read()
{
	ll x=0,w=1; char c=getchar();
	while(c<'0'||c>'9') {if(c=='-') w=-1; c=getchar();}
	while(c<='9'&&c>='0') {x=(x<<1)+(x<<3)+c-'0'; c=getchar();}
	return w==1?x:-x;
}
const int N=1e5+10;
ll mi,mx;
ll t[N],h[N],n,s;
int main()
{
    n=read(),s=read();
    mi=read(),mx=read();
    rep(i,1,n) t[i]=read();
    rep(i,1,n) h[i]=read();




    ll ans1=0,tmp1=s;
    rep(i,1,n)
    {
        if(h[i]>=mi) continue;
        if(tmp1>=t[i]) ans1++,tmp1-=t[i];
    }

    ll ans2=0,tmp2=s;
    rep(i,1,n)
    {
        if(h[i]<mx) {
            if(tmp2>=t[i]) ans2++,tmp2-=t[i];
        }
        else{
            if(tmp2>=2ll*t[i]) ans2++,tmp2-=2ll*t[i];
        }

    }
    printf("%lld %lld\n",ans1,ans2);



}

 

B-分組

做法:首先,根據題意,合理分組的答案一定是存在的,用01染色開始染色,染完色 再判斷一下當前節點是否連有兩個跟自己一組的,有  自己則換組,這題不知道是不是數據的問題,vector正向建圖wa   用鏈式前向星建圖卻A了

#include<iostream>//非
using namespace std;
const int k=3e5+3;
int n,m,cnt,shu[k],head[k],nxt[k],ans[k];
void add(int x,int y){shu[++cnt]=y;nxt[cnt]=head[x];head[x]=cnt;}
void dfs(int x){
    int s=0;
    for(int i=head[x];i;i=nxt[i]){
        if(!ans[shu[i]]) ans[shu[i]]=ans[x]^3,dfs(shu[i]);
        if(ans[shu[i]]==ans[x]) s++;
    }
    if(s>=2) ans[x]^=3;
}
int main(){
    cin>>n>>m;
    for(int i=1,x,y;i<=m;i++) cin>>x>>y,add(x,y),add(y,x);
    for(int i=1;i<=n;i++) if(!ans[i]) ans[i]=1,dfs(i);
    for(int i=1;i<=n;i++) cout<<ans[i]<<" ";
return 0;
}

vector:

#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define ll long long
#define maxn 1005
#define inf 1e9
#define pb push_back
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define per(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
 
inline ll read()
{
    ll x=0,w=1; char c=getchar();
    while(c<'0'||c>'9') {if(c=='-') w=-1; c=getchar();}
    while(c<='9'&&c>='0') {x=(x<<1)+(x<<3)+c-'0'; c=getchar();}
    return w==1?x:-x;
}
const int N=1e5+10;
vector<int>G[N];
int n,m,col[N];
void dfs(int u)
{
    int cnt=0;
    for(int v:G[u]){
        if(!col[v])  col[v]=3-col[u],dfs(v);
        if(col[u]==col[v]) cnt++;
    }
    if(cnt>=2) col[u]=3-col[u];
}
int main()
{
    n=read(),m=read();
    rep(i,1,m)
    {
        int u=read(),v=read();
        G[u].push_back(v);
        G[v].push_back(u);
    }
    rep(i,1,n) if(!col[i]) col[i]=1,dfs(i);
    rep(i,1,n) printf("%d ",col[i]);
}

 

C-紅球進黑洞

做法:這題很有意思,但看到好多暴力就過了,數據是真水,正解應該是對每一個數 進行 二進制拆分,然後對30 位01數字進行區間求和 和異或的維護。 sum[id][i] 記錄id節點第i位 爲1的個數,異或的話  0  和 1的數量互換就可以了。

#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define ll long long
#define maxn 1005
#define inf 1e9
#define pb push_back
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define per(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
 
inline ll read()
{
    ll x=0,w=1; char c=getchar();
    while(c<'0'||c>'9') {if(c=='-') w=-1; c=getchar();}
    while(c<='9'&&c>='0') {x=(x<<1)+(x<<3)+c-'0'; c=getchar();}
    return w==1?x:-x;
}
const int N=1e5+10;
ll sum[4*N][32],lazy[4*N],n,m,f[32];
void build(int id,int l,int r)
{
    if(l==r){
        ll x=read();
        for(int i=30;~i;--i){
            if(x&f[i]) sum[id][i]++;
        }
        return ;
    }
    int mid=l+r>>1;
    build(id<<1,l,mid);
    build(id<<1|1,mid+1,r);
    for(int i=0;i<=30;++i) sum[id][i]=sum[id<<1][i]+sum[id<<1|1][i];
}
 
void push(int id,int l,int r)
{
    if(lazy[id]){
        lazy[id<<1]^=lazy[id];
        lazy[id<<1|1]^=lazy[id];
        for(int i=0;i<=30;++i){
            if(lazy[id]&f[i]) {
                int mid=l+r>>1;
                sum[id<<1][i]=mid-l+1-sum[id<<1][i];
                sum[id<<1|1][i]=r-mid-sum[id<<1|1][i];
 
            }
        }
        lazy[id]=0;
    }
}
ll qu(int id,int l,int r,int ql,int qr)
{
    if(ql<=l&&r<=qr){
        ll ans=0;
        for(int i=0;i<=30;++i) ans=ans+sum[id][i]*f[i];
        return ans;
    }
    push(id,l,r);
    ll ans=0,mid=l+r>>1;
    if(ql<=mid) ans+=qu(id<<1,l,mid,ql,qr);
    if(qr>mid) ans+=qu(id<<1|1,mid+1,r,ql,qr);
    return ans;
}
void up(int id,int l,int r,int ql,int qr,ll k)
{
    if(ql<=l&&r<=qr){
        lazy[id]^=k;
        for(int i=0;i<=30;++i) {
            if(k&f[i]) sum[id][i]=r-l+1-sum[id][i];
        }
        return ;
    }
    push(id,l,r);
    int mid=l+r>>1;
    if(ql<=mid) up(id<<1,l,mid,ql,qr,k);
    if(qr>mid) up(id<<1|1,mid+1,r,ql,qr,k);
    for(int i=0;i<=30;++i) sum[id][i]=sum[id<<1][i]+sum[id<<1|1][i];
}
int main()
{
    f[0]=1;
    for(int i=1;i<=30;++i) f[i]=f[i-1]*2;
    n=read(),m=read();
    build(1,1,n);
    while(m--)
    {
        int ty=read(),l=read(),r=read();
        if(ty==1){
            ll ans=qu(1,1,n,l,r);
            printf("%lld\n",ans);
        }
        else{
            ll k=read();
            up(1,1,n,l,r,k);
        }
    }
}

D-遊戲

沒寫出來,百度的做法:博客

其實只需要看左上角就行了,因爲題目描述寫的很清楚,三個人的操作都是爲了
BLUESKY007能贏,所以遊戲一定會結束,那麼當橫縱座標最大的非 B 顏色方格變爲 B 顏
色時,可操作的方格範圍顯然是趨向收斂的,又因爲操作規則的要求,左上角的方格在每
次操作中都會按規則進行變換,當可操作範圍收斂到左上角且左上角變爲 B 顏色時,遊
戲結束,所以無論中間的操作是怎樣進行的,最終左上角的方格一定會變爲 B 顏色,而且
進行操作的人數和操作變換長度相同,所以我們只需要判斷左上角方格的顏色即可。

 

#include<bits/stdc++.h>
using namespace std;
char maze[1000 + 5][1000 + 5];
int main() {
	int t;
	cin>>t;
	int n,m;
	while(t--) {
		scanf("%d%d",&n,&m);
		for(int i=0; i<n; i++) {
			cin>>maze[i];
		}
		if(maze[0][0]=='R') puts("dreagonm");
		else if(maze[0][0]=='G') puts("fengxunling");
		else puts("BLUESKY007");
	}
}

E-積木大賽

做法:做了這麼多這類題,區間加一減一  首先就考慮差分去了。然後發現答案就是等於 正的 差分之和,試一發,A了。

#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define ll long long
#define maxn 1005
#define inf 1e9
#define pb push_back
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define per(i,a,b) for(int i=a;i>=b;i--)
using namespace std;

inline ll read()
{
	ll x=0,w=1; char c=getchar();
	while(c<'0'||c>'9') {if(c=='-') w=-1; c=getchar();}
	while(c<='9'&&c>='0') {x=(x<<1)+(x<<3)+c-'0'; c=getchar();}
	return w==1?x:-x;
}
const int N=1e5+10;
ll a[N];
int n;
int main()
{
   n=read();
   rep(i,1,n) a[i]=read();
   ll ans=0;
   rep(i,1,n)
   {
       if(a[i]-a[i-1]>0) ans+=a[i]-a[i-1];
   }
   cout<<ans<<endl;


}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章