《牛客算法周周练11》

B:

二分图的染色应用。

首先,注意题目的信息。

每个人最多有三个认识的人。

那么,我们可以思考,当有三个人和一个人连边时。

如果有两个人和他同色,一个人不同色。

那么将这个人反转,就变成了,一个人和他同色,两个人不同色。

那么可以发现,对于每一个人,翻转后可以减少同色的数量。

可以证明,必定存在解。即存在排列,分散两堆人。

思路:

先对每个没有染色过的点染色,当一个点和它相邻的点的同色点>=2时,就翻转它的颜色。

注意的是,对于一个没有染色过的点,染色过后也需要判断是否和u同色。

因为这个v点可能在dfs下层被翻转.

Code:

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int,int> pii;
const int N = 2e5+5;
const int M = 1e6+5;
const int Mod = 1e9+7;
#define pi acos(-1)
#define INF 1e18
#define INM INT_MIN
#define rg register
#define pb(a)  push_back(a)
#define mk(a,b) make_pair(a,b)
#define dbg(x) cout << "now this num is " << x << endl;
#define met0(axx) memset(axx,0,sizeof(axx));
#define metf(axx) memset(axx,-1,sizeof(axx));
#define sd(ax) scanf("%d",&ax)
#define sld(ax) scanf("%lld",&ax)
#define sldd(ax,bx) scanf("%lld %lld",&ax,&bx)
#define sdd(ax,bx) scanf("%d %d",&ax,&bx)
#define sddd(ax,bx,cx) scanf("%d %d %d",&ax,&bx,&cx)
#define sfd(ax) scanf("%lf",&ax)
#define sfdd(ax,bx) scanf("%lf %lf",&ax,&bx)
#define pr(a) printf("%d\n",a)
#define plr(a) printf("%lld\n",a)
struct Node{int next,to;}e[N<<1];
int cnt = 0,head[N],col[N];
inline void add(int u,int v)
{
    e[++cnt].to = v,e[cnt].next = head[u],head[u] = cnt;
}
void dfs(int u,int c)
{
    col[u] = c;
    int ma = 0;
    for(int i = head[u];i;i = e[i].next)
    {
        int v = e[i].to;
        if(col[v] == 0) dfs(v,c^3);
        if(col[v] == col[u]) ma++;
    }
    if(ma >= 2) col[u] ^= 3;
}
void run()
{
    int n,m;sdd(n,m);
    while(m--)
    {
        int u,v;sdd(u,v);
        add(u,v);add(v,u);
    }
    for(int i = 1;i <= n;++i) if(col[i] == 0) dfs(i,1);
    for(int i = 1;i <= n;++i) printf("%d%c",col[i],i == n ? '\n' : ' ');
}  
int main()
{
    run();
    system("pause");
    return 0;
}
View Code

 D:

博弈论。

发现,对于每次变换,左上角的(1,1)始终都会变换。

对于结果,肯定是所有都为B。

所有对于左上角,肯定是最终变为B。

然后R-G-B三色变换,正好是一个周期。

所以每次经过一个周期变换,相当于没有操作。

所以只需要判断(1,1)一开始的状态即可。

Code:

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int,int> pii;
const int N = 2e5+5;
const int M = 1e6+5;
const int Mod = 1e9+7;
#define pi acos(-1)
#define INF 1e18
#define INM INT_MIN
#define rg register
#define pb(a)  push_back(a)
#define mk(a,b) make_pair(a,b)
#define dbg(x) cout << "now this num is " << x << endl;
#define met0(axx) memset(axx,0,sizeof(axx));
#define metf(axx) memset(axx,-1,sizeof(axx));
#define sd(ax) scanf("%d",&ax)
#define sld(ax) scanf("%lld",&ax)
#define sldd(ax,bx) scanf("%lld %lld",&ax,&bx)
#define sdd(ax,bx) scanf("%d %d",&ax,&bx)
#define sddd(ax,bx,cx) scanf("%d %d %d",&ax,&bx,&cx)
#define sfd(ax) scanf("%lf",&ax)
#define sfdd(ax,bx) scanf("%lf %lf",&ax,&bx)
#define pr(a) printf("%d\n",a)
#define plr(a) printf("%lld\n",a)
string mp[1005];
void run()
{
    int t;sd(t);
    while(t--)
    {
        int n,m;sdd(n,m);
        for(int i = 0;i < n;++i) cin >> mp[i];
        if(mp[0][0] == 'G') printf("fengxunling\n");
        else if(mp[0][0] == 'R')printf("dreagonm\n");
        else printf("BLUESKY007\n");
    }
}  
int main()
{
    run();
    system("pause");
    return 0;
}
View Code

C:

线段树维护一下二进制位的1即可。

注意0应该用num-1来,记0的个数会记空的位置.

Code:

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int,int> pii;
const int N = 1e5+5;
const int M = 1e6+5;
const int Mod = 1e9+7;
#define pi acos(-1)
#define INF 1e18
#define INM INT_MIN
#define rg register
#define pb(a)  push_back(a)
#define mk(a,b) make_pair(a,b)
#define dbg(x) cout << "now this num is " << x << endl;
#define met0(axx) memset(axx,0,sizeof(axx));
#define metf(axx) memset(axx,-1,sizeof(axx));
#define sd(ax) scanf("%d",&ax)
#define sld(ax) scanf("%lld",&ax)
#define sldd(ax,bx) scanf("%lld %lld",&ax,&bx)
#define sdd(ax,bx) scanf("%d %d",&ax,&bx)
#define sddd(ax,bx,cx) scanf("%d %d %d",&ax,&bx,&cx)
#define sfd(ax) scanf("%lf",&ax)
#define sfdd(ax,bx) scanf("%lf %lf",&ax,&bx)
#define pr(a) printf("%d\n",a)
#define plr(a) printf("%lld\n",a)
struct Node
{
    int L,r;
    LL sum = 0,tag = 0,cnt[25];
}node[N<<2];
LL a[N];
void Pushup(int idx)
{
    node[idx].sum = node[idx<<1].sum + node[idx<<1|1].sum;
    for(int i = 0;i < 25;++i)
    {
        node[idx].cnt[i] = node[idx<<1].cnt[i]+node[idx<<1|1].cnt[i];
    }
}
void Pushdown(int idx)
{
    if(node[idx].tag != 0)
    {
        int tag = node[idx].tag;
        int num1 = (node[idx<<1].r-node[idx<<1].L+1);
        int num2 = (node[idx<<1|1].r-node[idx<<1|1].L+1);
        for(int i = 0;i < 25;++i)
        {
            int t = (tag>>i)&1;
            int a1 = node[idx<<1].cnt[i];
            int b1 = node[idx<<1|1].cnt[i];
            if(t == 1)
            {
                node[idx<<1].sum += (1<<i)*(num1-a1);
                node[idx<<1].sum -= (1<<i)*a1;
                node[idx<<1|1].sum += (1<<i)*(num2-b1);
                node[idx<<1|1].sum -= (1<<i)*b1;
                node[idx<<1].cnt[i] = num1-a1;
                node[idx<<1|1].cnt[i] = num2-b1;
            }
        }
        node[idx<<1].tag ^= tag;
        node[idx<<1|1].tag ^= tag;
        node[idx].tag = 0;
    }
}
void build(int L,int r,int idx)
{
    node[idx].L = L,node[idx].r = r;
    if(L == r)
    {
        node[idx].sum = a[L];
        for(int i = 0;i < 25;++i)
        {
            int t = (a[L]>>i)&1;
            if(t == 1) node[idx].cnt[i]++;
        }
       // for(int i = 0;i < 25;++i) printf("i is %d cnt is %d\n",i,node[idx].cnt[i]);
        return ;
    }
    int mid = (node[idx].L+node[idx].r)>>1;
    build(L,mid,idx<<1);
    build(mid+1,r,idx<<1|1);
    Pushup(idx);
}
void update(int L,int r,int idx,int k)
{
    if(node[idx].L >= L && node[idx].r <= r)
    {
        int num = (node[idx].r-node[idx].L+1);
        for(int i = 0;i < 25;++i)
        {
            int t = (k>>i)&1;
            int a1 = node[idx].cnt[i];
            if(t == 1)
            {
                node[idx].sum += (1<<i)*(num-a1);
                node[idx].sum -= (1<<i)*a1;
                node[idx].cnt[i] = num-a1;
              //  printf("i is %d a1 is %d sum is %d\n",i,a1,node[idx].sum);
            }
        }
        node[idx].tag ^= k;
    }
    else
    {
        Pushdown(idx);
        int mid = (node[idx].L+node[idx].r)>>1;
        if(mid >= L) update(L,r,idx<<1,k);
        if(mid < r) update(L,r,idx<<1|1,k);
        Pushup(idx);
    }
}
LL query(int L,int r,int idx)
{
    if(node[idx].L >= L && node[idx].r <= r) return node[idx].sum;
    int mid = (node[idx].L+node[idx].r)>>1;
    LL ans = 0;
    Pushdown(idx);
    if(mid >= L) ans += query(L,r,idx<<1);
    if(mid < r) ans += query(L,r,idx<<1|1);
    return ans;
}
void run()
{
    int n,m;sdd(n,m);
    for(int i = 1;i <= n;++i) sld(a[i]);
    build(1,n,1);
    while(m--)
    {
        int id;sd(id);
        if(id == 1)
        {
            int L,r;sdd(L,r);
            LL ans = query(L,r,1);
            plr(ans);
        }
        if(id == 2)
        {
            int L,r,k;sddd(L,r,k);
            update(L,r,1,k);
        }
    }
}  
int main()
{
    run();
   // system("pause");
    return 0;
}
View Code

 

posted @ 2020-06-17 08:32  levill  阅读(195)  评论(0编辑  收藏  举报