Day3上

 

T1

星空
【问题描述】
你是能看到第一题的friends 呢。
——hja
点点星空是一张𝑁 × 𝑀的棋盘,左下角有颗星星。尤和千每次可以将星星向
右边、右上、上边移动一格。尤和千轮流移动,尤先手,问尤是否必胜?
【输入格式】
多组数据,每行两个整数𝑁, 𝑀,当𝑁 = 𝑀 = 0时数据停止。
【输出格式】
对于每组数据,如果尤必胜输出“Yuri”,否则输出“Chito”。
【样例输入】
5 3
5 4
6 6
0 0
【样例输出】
Chito
Yuri
Yuri
【数据范围与规定】
对于50%的数据,1 ≤ 𝑁, 𝑀 ≤ 10。
对于100%的数据,1 ≤ 𝑁, 𝑀 ≤ 1000。

思路:

  我是想,用布尔型的dp推ij这种状态,谁必赢。

  如果这局1必输,那么  ,f[i+1][j]=f[i][j+1]=f[i+1][j+]=1 必赢

 都是奇数,先手必败,否则先手必胜。 

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<cstring>
#include<cmath>
#include<ctime>
using namespace std;
const int N=1001;
int n,m,tmp;
bool f[1010][1010];
void first()
{
    for(int i=1;i<=N;i++)
    f[i][0]=!f[i-1][0];
    for(int j=0;j<=N;j++)
    for(int i=j;i<=N;i++)
        if(!f[i][j])    f[i+1][j]=f[i][j+1]=f[i+1][j+1]=1;
}
int main()
{
    freopen("star.in","r",stdin);
    freopen("star.out","w",stdout);    
    first();
    scanf("%d%d",&n,&m);
    while(n||m)
    {
        tmp=max(n,m);
        m=min(n,m);n=tmp;
        m--;n--;
        if(f[n][m])    printf("Yuri\n");
        else printf("Chito\n");
        scanf("%d%d",&n,&m);
    }
    return 0;
}
第一遍

战争
【问题描述】
你是能看到第二题的 friends呢。
—— laekov
战场上有 𝑁个数,两异或可以得到 𝑁×𝑁−12个数,求这些中前 𝐾大的 数 的和。
【输入格式】
第一行两个 整数 𝑁,𝐾。
接下来一行 𝑁个数 。
【输出格式】
一行个整数代表答案 对109+7取模之后的结果 。
【样例输入】
3 1
1 2 3
【样例输出】
3
【数据范围与规定】
对于 40%的数据 ,𝑁≤100。
对于另外 20%的数据, 𝐾=1。
对于另外 20%的数据,所有不超过 1023。
对于 100%的数据 ,1≤𝑁≤5×104,所有数不超过 ,所有数不超过 ,所有数不超过 231−1且非负 ,𝐾一定 合法 。

有点怵

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<cstring>
#include<cmath>
#include<ctime>
using namespace std;
const int N=1e4*5+100;
const int M=1025;
int n,k;
int a[N],maxn;
bool sum[N];
int main()
{
    freopen("war.in","r",stdin);
    freopen("war.out","w",stdout);
    scanf("%d%d",&n,&k);
    for(int i=1;i<=n;i++)    
        scanf("%d",&a[i]);
    
    if(n<=100)
    {
        priority_queue<int>q;
        for(int i=1;i<=n;i++)
        for(int j=i+1;j<=n;j++)
            q.push(a[i]^a[j]);
        long long ans=0;
        for(int i=1;i<=k;i++)
        {
            ans+=q.top();
            q.pop();
        }
        cout<<ans;
        return 0;
    }
    
    if(k==1)
    {
        int maxn=0;
        for(int i=1;i<=n;i++)
        for(int j=i+1;j<=n;j++)
        maxn=max(maxn,a[i]^a[j]);
        cout<<maxn;
        return 0;
    }
    
    for(int i=1;i<=n;i++)
        sum[a[i]]=1;
    for(int i=1;i<=M;i++)
    if(sum[i])
        for(int j=1;j<=n;j++)
        maxn=max(maxn,a[j]^i);
    cout<<maxn;
    return 0;
}
第一遍0

:暴力求

:分治从大到小看看每一位能否得到

 :放到桶里

 正解 二分+tree树

  先求第K大,把比他大的加。二分K大数,找有多少个比他大。

无题
【问题描述】
你是能看到第三题的 friends呢。
—— aoao
世界已无名字,而题目仍然存在。
𝑁个数, 𝑀次操作,每询问 区间第 𝑘大,或者给区间加上一个数 。
【输入格式】
第一行 两个整数 𝑁,𝑀。
接下来一行 𝑁个数代表初始值。
接下来 𝑀行,每第一个数 行,每第一个数 行,每第一个数 行,每第一个数 𝑜𝑝𝑡代表操作种类。如果 代表操作种类。如果 代表操作种类。如果 代表操作种类。如果 𝑜𝑝𝑡=0,那么接下来三 ,那么接下来三 ,那么接下来三 个数 𝑙,𝑟,𝑘,代表询问第 ,代表询问第 𝑙到第 𝑟个数中第 𝑘大的是多少;如果 大的是多少;如果 𝑜𝑝𝑡=1,那么接下来 ,那么接下来 三个数 𝑙,𝑟,𝑣,代表给第 𝑙到第 𝑟个数全部加上 𝑣。
【输出格式】
对于每次询问,输出答案 。如果答案不存在,输出 −1。
【样例输入】
5 3
1 2 3 4 5
0 2 3 1
1 2 4
0 2 3 1
【样例输出】
3
6
【数据规模与约定】
对于 30%的数据, 1≤𝑁,𝑀≤1000。
对于另外 20%的数据, 𝑘=1。
对于另外 20%的数据,没有修改操作。//主席树或 离线(莫队+堆)
对于 100%的数据, 1≤𝑁,𝑀≤105,1≤𝐾≤10。

希望有分。

a#include<iostream>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<cstring>
#include<cmath>
#include<ctime>
using namespace std;
const int N=1e5+2;
int n,m;
int a[N];
int d[N];
int main()
{
    freopen("noname.in","r",stdin);
    freopen("noname.out","w",stdout);
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    for(int i=1,opt,l,r,v;i<=m;i++)
    {
        scanf("%d%d%d%d",&opt,&l,&r,&v);    
        if(opt)
        {
            d[l]+=v,d[r+1]-=v;
        }else
        {
            if(v==1)
            {
                int j,o,tot=0,ans=0;
                for(j=1;j<=l;j++)    tot+=d[j];            
                for(j=l;j<=r;j++)
                ans=max(ans,tot+a[j]),tot+=d[j+1];
                printf("%d\n",ans);
                continue;
            }
            priority_queue<int>q;
            int tot=0,o,j;
            for(j=1;j<=l;j++)    tot+=d[j];            
            for(j=l;j<=r;j++)
                q.push(a[j]+tot),tot+=d[j+1];
            for(j=1;j<v;j++)
            {o=q.top();q.pop();}
            o=q.top();
            printf("%d\n",o);
        }
    }
    return 0;
}
第一遍0

 没看到-1

线段树,维护前十大。

如何更新?  合并子树的,前十大,指针移动。

修改?      整个区间的修改,前十大+v。

合并,加法操作,重载运算。

如何返回前十大数,

posted @ 2017-10-30 09:41  浪矢-CL  阅读(410)  评论(0编辑  收藏  举报