Div4 思维总结

B题题目中为不能从蓝色中辨别出绿色,可将蓝色也变为绿色,这个点没想到。

D. Line

题意:每个人可选择向左看或者向右看,将看到的人数累加,可一次改变k个人的方向,要加累加值最大。
思路:乍一看感觉很复杂,不知道从哪开始做。但会发现,只有改变方向看到的人数增多,改变才有意义;在修改完一定人数后,会无需继续修改。
1.将改变方向后人数增多的值进行记录,再进行降序排列,统计前缀和,改变数目为cnt。
2.再1~cnt的数目中,累加值为g(初始排列看到的人数)+b[i](前缀和);再cnt+1 ~n的数目中,答案恒为g+b[cnt]
代码:

#include<bits/stdc++.h>
#define int long long
#define endl '\n'
#define For(i,a,b) for(i=(a);i<=(b);++i)
#define ios (ios::sync_with_stdio(false),cin.tie(0),cout.tie(0))
using namespace std;
const int N=1e6+7;
const int inf=0x3f3f3f3f;
const int mod=1e9+7;
int n,a[N],b[N];
char s[N];
bool cmp(int a,int b) {return a>b;}
void solve()
{
    cin>>n;
    for(int i=0;i<=n;i++) a[i]=b[i]=0;
    for(int i=1;i<=n;i++)
        cin>>s[i];
    int g=0;
    for(int i=1;i<=n;i++)
    {
        if(s[i]=='L') g+=i-1;
        else g+=n-i;
    }
    //cout<<g<<endl;
    int cnt=0;
    for(int i=1;i<=n;i++)
    {
        if(s[i]=='L')
        {
            if(n-i>i-1) a[++cnt]=n-i-(i-1);
        }
        else
        {
            if(n-i<i-1) a[++cnt]=i-1-(n-i);
        }
    }
    sort(a+1,a+1+cnt,cmp);
    for(int i=1;i<=n;i++)
        b[i]=a[i]+b[i-1];
    int p;
    for(int i=1;i<=n;i++)
    {
        if(i<=cnt)
            cout<<g+b[i]<<" ";
        else
            cout<<g+b[cnt]<<" ";
    }
    cout<<endl;
}
signed main()
{
    //ios;
    int T;cin>>T;
    while(T--)
        solve();
    return 0;
}


E. Counting Rectangles

知识点:矩阵二维前缀和、差分
思路:
1.从高度和宽度的数据范围入手,由于都是1~1000,最高达到1e6次方,可统计n个矩阵中,在i行j列时面积的累加值。
2.由于不能重叠,需要加1和减1的操作,利用差分求出h1~h2和w1 ~w2中的乘积的累加和。

#include<bits/stdc++.h>
#define int long long
#define endl '\n'
#define For(i,a,b) for(i=(a);i<=(b);++i)
#define ios (ios::sync_with_stdio(false),cin.tie(0),cout.tie(0))
using namespace std;
const int N=1e6+7;
const int inf=0x3f3f3f3f;
const int mod=1e9+7;
bool cmp1(int a,int b) {return a>b;}
int n,q,a[1005][1005],b[1005][1005];

void solve()
{
    cin>>n>>q;
    for(int i=0;i<1005;i++)
        for(int j=0;j<1005;j++)
        a[i][j]=b[i][j]=0;
    for(int i=1;i<=n;i++)
    {
        int x,y;cin>>x>>y;
        a[x][y]+=x*y;
    }
    for(int i=1;i<=1000;i++)
        for(int j=1;j<=1000;j++)
        b[i][j]=b[i-1][j]+b[i][j-1]-b[i-1][j-1]+a[i][j];
    while(q--)
    {
        int h1,w1,h2,w2;cin>>h1>>w1>>h2>>w2;
        h1++,w1++,h2--,w2--;
        cout<<b[h2][w2]-b[h1-1][w2]-b[h2][w1-1]+b[h1-1][w1-1]<<endl;
    }
}
signed main()
{
    //ios;
    int T;cin>>T;
    while(T--)
        solve();
    return 0;
}

F. L-shapes

题意:判断图形"L",每两个之间不能有边和角的重叠。
思路:
1.每个"*"格子间的8个方向的格子,只能出现三个“ * ”
2.先判断是否能构成图形L,对于判断过的“”进行标记;在判断每个中8个方向的格子是否只有三个*

#include<bits/stdc++.h>
#define int long long
#define endl '\n'
#define For(i,a,b) for(i=(a);i<=(b);++i)
#define ios (ios::sync_with_stdio(false),cin.tie(0),cout.tie(0))
using namespace std;
const int N=1e6+7;
const int inf=0x3f3f3f3f;
const int mod=1e9+7;
int n,m;
bool vis[105][105];
char a[105][105];
bool check1(int x,int y)
{
    int sum=0;
    for(int i=-1;i<=1;i++)
        for(int j=-1;j<=1;j++)
            if(a[x+i][y+j]=='*') sum++;
    return sum==3;
}
bool check2(int x,int y)
{
    int sum=1;
    vis[x][y]=1;
    int flag=0;
    if(a[x][y+1]=='*')
        vis[x][y+1]=1,sum++;
    if(a[x+1][y+1]=='*')
        vis[x+1][y+1]=1,sum++;
    if(a[x+1][y]=='*')
        vis[x+1][y]=1,sum++;
    if(a[x+1][y-1]=='*')
        vis[x+1][y-1]=1,sum++;
    return sum==3;
}
void solve()
{
    cin>>n>>m;
    for(int i=0;i<=n+5;i++)
        for(int j=0;j<=m+5;j++)
            a[i][j]='0',vis[i][j]=0;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++) cin>>a[i][j];
    int g=1;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            if(a[i][j]=='*'&&!vis[i][j])
            {
                if(check2(i,j)==0)
                {
                    //cout<<i<<" "<<j<<endl;
                    g=0;break;
                }
            }
            if(a[i][j]=='*')
            {
                if(check1(i,j)==0)
                {
                    g=0;break;
                }
            }
        }
        if(g==0) break;
    }
    if(g)
        cout<<"YES"<<endl;
    else
        cout<<"NO"<<endl;
}
signed main()
{
    //ios;
    int T;cin>>T;
    while(T--)
        solve();
    return 0;
}


G. Even-Odd XOR

题意:下标为奇数的异或值和下标为偶数的异或值相异或结果为0.
思路:看出是构造题,思路就要灵活一点,别老想着去找规律。。。。
1.从题意中需理解到是不是所有元素像疑惑结果为0即可。
2.运用公式b^(a|b)^a==0,可知前n-2的数可随意放置,第n-1个数为a|b,第n个数为a。
3.需特判若前n-2个数异或结果为0,则最后两个数时同一个值,不满足题意。可取修改第一个元素的值。

#include<bits/stdc++.h>
#define int long long
#define endl '\n'
#define For(i,a,b) for(i=(a);i<=(b);++i)
#define ios (ios::sync_with_stdio(false),cin.tie(0),cout.tie(0))
using namespace std;
const int N=1e6+7;
const int inf=0x3f3f3f3f;
const int mod=1e9+7;
bool cmp1(int a,int b) {return a>b;}
int n,a[N],s;

void solve()
{
    s=0;
    cin>>n;
    for(int i=0;i<n-2;i++)
    {
        a[i]=i;s^=i;
    }
    if(s==0)
    {
        a[0]=(1<<30)-1;
        s=(1<<30)-1;
    }
    a[n-2]=s|(1<<30);
    a[n-1]=(1<<30);
    for(int i=0;i<n;i++)
        cout<<a[i]<<" ";
    cout<<endl;
}
signed main()
{
    //ios;
    int T;cin>>T;
    while(T--)
        solve();
    return 0;
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值