CF #316(Div2)

A:水题,读懂题意就不难了。

#include<stdio.h>
#include<iostream>
#include<string>
#include<string.h>
#include<algorithm>
#include<iomanip>
#include<vector>
#include<time.h>
#include<queue>
#include<stack>
#include<iterator>
#include<math.h>
#include<stdlib.h>
#include<limits.h>
#include<map>
#include<set>
//#define ONLINE_JUDGE
#define eps 1e-8
#define INF 0x7fffffff
#define FOR(i,a) for((i)=0;i<(a);(i)++)
#define MEM(a) (memset((a),0,sizeof(a)))
#define sfs(a) scanf("%s",a)
#define sf(a) scanf("%d",&a)
#define sfI(a) scanf("%I64d",&a)
#define pf(a) printf("%d\n",a)
#define pfI(a) printf("%I64d\n",a)
#define pfs(a) printf("%s\n",a)
#define sfd(a,b) scanf("%d%d",&a,&b)
#define sft(a,b,num) scanf("%d%d%d",&a,&b,&num)
#define for1(i,a,b) for(int i=(a);i<b;i++)
#define for2(i,a,b) for(int i=(a);i<=b;i++)
#define for3(i,a,b)for(int i=(b);i>=a;i--)
#define MEM1(a) memset(a,0,sizeof(a))
#define MEM2(a) memset(a,-1,sizeof(a))
#define ll __int64
const double PI=acos(-1.0);
template<class T> T gcd(T a,T b){return b?gcd(b,a%b):a;}
template<class T> T lcm(T a,T b){return a/gcd(a,b)*b;}
template<class T> inline T Min(T a,T b){return a<b?a:b;}
template<class T> inline T Max(T a,T b){return a>b?a:b;}
using namespace std;
//#pragma comment(linker,"/STACK:1024000000,1024000000")
int n,m;
#define M 110
#define N 2000010
#define Mod 258280327
#define p(x,y) make_pair(x,y)
int a[110][110];
int vote[110];
int main(){
#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
//  freopen("out.txt", "w", stdout);
#endif
    while(sfd(n,m)!=EOF){
        memset(vote,0,sizeof vote);
        for(int i=1;i<=m;i++){
            int flag,mmax=-1;
            for(int j=1;j<=n;j++){
                sf(a[i][j]);
                if(a[i][j]>mmax){
                    mmax = a[i][j];
                    flag = j;
                }
            }
            vote[flag]++;
        }
        int ans,mmax=-1;
        for(int i=1;i<=n;i++){
            if(mmax<vote[i]){
                mmax = vote[i];
                ans = i;
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}

B:其实稍微理解下,就能发现,如果要使得获胜概率较大,那么不是m-1就是m+1。但是这道题目还有个坑。。就是当n=1时,那么我们选的数就只能是1了。。

#include<stdio.h>
#include<iostream>
#include<string>
#include<string.h>
#include<algorithm>
#include<iomanip>
#include<vector>
#include<time.h>
#include<queue>
#include<stack>
#include<iterator>
#include<math.h>
#include<stdlib.h>
#include<limits.h>
#include<map>
#include<set>
//#define ONLINE_JUDGE
#define eps 1e-8
#define INF 0x7fffffff
#define FOR(i,a) for((i)=0;i<(a);(i)++)
#define MEM(a) (memset((a),0,sizeof(a)))
#define sfs(a) scanf("%s",a)
#define sf(a) scanf("%d",&a)
#define sfI(a) scanf("%I64d",&a)
#define pf(a) printf("%d\n",a)
#define pfI(a) printf("%I64d\n",a)
#define pfs(a) printf("%s\n",a)
#define sfd(a,b) scanf("%d%d",&a,&b)
#define sft(a,b,num) scanf("%d%d%d",&a,&b,&num)
#define for1(i,a,b) for(int i=(a);i<b;i++)
#define for2(i,a,b) for(int i=(a);i<=b;i++)
#define for3(i,a,b)for(int i=(b);i>=a;i--)
#define MEM1(a) memset(a,0,sizeof(a))
#define MEM2(a) memset(a,-1,sizeof(a))
#define ll __int64
const double PI=acos(-1.0);
template<class T> T gcd(T a,T b){return b?gcd(b,a%b):a;}
template<class T> T lcm(T a,T b){return a/gcd(a,b)*b;}
template<class T> inline T Min(T a,T b){return a<b?a:b;}
template<class T> inline T Max(T a,T b){return a>b?a:b;}
using namespace std;
//#pragma comment(linker,"/STACK:1024000000,1024000000")
int n,m;
#define M 110
#define N 2000010
#define Mod 258280327
#define p(x,y) make_pair(x,y)
int a[110][110];
int vote[110];
int main(){
#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
//  freopen("out.txt", "w", stdout);
#endif
    while(sfd(n,m)!=EOF){
            int res1 = m-1;
            int res2 = n-m;
            if(n == 1)
                printf("%d\n",n);
            else if(res1>=res2&&res1>=1)
                printf("%d\n",m-1);
            else if(res1<res2&&m+1<=n)
                printf("%d\n",m+1);
    }
    return 0;
}

C:这道题目犯了好多傻逼的错误。。刚开始我竟然用了直接模拟的做法。。妥妥的超时了。正解是开始我们先用模拟计算出原字符串的performing次数ans,然后对于每一次的修改,假设修改的位置是x,那么我们记x-1和x+1位置上为’.’的个数是res,那么如果修改成的是’.’,结果就是ans+res;如果修改成的不是’.’,那么结果就是ans-res.这个结论只要自己手写一遍就看得出来。不过我又犯了个错误,就是当它修改时,我们要先判断修改的种类是否发生变化,即如果原来位置本来就是’.’,那我们修改完还是’.’,或者本来位置是字母,修改完还是字母,那这个就不会影响performing的次数了。

#include<stdio.h>
#include<iostream>
#include<string>
#include<string.h>
#include<algorithm>
#include<iomanip>
#include<vector>
#include<time.h>
#include<queue>
#include<stack>
#include<iterator>
#include<math.h>
#include<stdlib.h>
#include<limits.h>
#include<map>
#include<set>
//#define ONLINE_JUDGE
#define eps 1e-8
#define INF 0x7fffffff
#define FOR(i,a) for((i)=0;i<(a);(i)++)
#define MEM(a) (memset((a),0,sizeof(a)))
#define sfs(a) scanf("%s",a)
#define sf(a) scanf("%d",&a)
#define sfI(a) scanf("%I64d",&a)
#define pf(a) printf("%d\n",a)
#define pfI(a) printf("%I64d\n",a)
#define pfs(a) printf("%s\n",a)
#define sfd(a,b) scanf("%d%d",&a,&b)
#define sft(a,b,num) scanf("%d%d%d",&a,&b,&num)
#define for1(i,a,b) for(int i=(a);i<b;i++)
#define for2(i,a,b) for(int i=(a);i<=b;i++)
#define for3(i,a,b)for(int i=(b);i>=a;i--)
#define MEM1(a) memset(a,0,sizeof(a))
#define MEM2(a) memset(a,-1,sizeof(a))
#define ll __int64
const double PI=acos(-1.0);
template<class T> T gcd(T a,T b){return b?gcd(b,a%b):a;}
template<class T> T lcm(T a,T b){return a/gcd(a,b)*b;}
template<class T> inline T Min(T a,T b){return a<b?a:b;}
template<class T> inline T Max(T a,T b){return a>b?a:b;}
using namespace std;
//#pragma comment(linker,"/STACK:1024000000,1024000000")
int n,m;
#define M 110
#define N 300010
#define Mod 258280327
#define p(x,y) make_pair(x,y)
char ch[N];
//char tmp[N];
int solve(){
    int ans=0;
    stack<char>s;
    for(int i=0;i<n;i++){
        while(!s.empty() &&s.top() == '.' && ch[i] == '.' && i<n){
            i++;
            ans++;
        }
        s.push(ch[i]);
    }
    return ans;
}
int main(){
#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
//  freopen("out.txt", "w", stdout);
#endif
    while(sfd(n,m)!=EOF){
        sfs(ch);
        int x;
        char cr;
        int ans = solve();
        for(int i=0;i<m;i++){
            scanf("%d %c",&x,&cr);
            x--;
            int res=0;
            if(ch[x] == '.' && cr == '.'){
                printf("%d\n",ans);
                continue;
            }
            if((ch[x]>='a'&&ch[x]<='z') && (cr>='a'&&cr<='z')){
                printf("%d\n",ans);
                continue;
            }
            if(x-1>=0 && ch[x-1] == '.') res++;
            if(x+1<n && ch[x+1] == '.') res++;
            if(cr == '.')
                ans += res;
            else
                ans -= res;
            ch[x] = cr;
            printf("%d\n",ans);
        }
    }
    return 0;
}

D:这个参照了别人的想法,自己写的超时了。
首先我们要知道给你几个字母,它们是否能组成一个回文子串的条件是 含有奇数个数的字母要么为0,要么为1,对应的就是组成偶数长度和奇数长度的回文子串。
这里我们用二进制来表示是否含有某个字母,假设输入的是ch,那么每个位置上的表示就是1<<(ch[i]-‘a’)。
预处理的时候,我们将相同高度的点存放在一个vector里面,vector是一个结构体,有两个参数,一个是搜索的序号,另外一个就是表示状态的二进制表示。
我们知道,如果是在同一个subtree里面,那么它们搜索的次序是连续的,那么我们用in[v]表示v这个点刚开始 被访问的次序序号,out[v]表示v这个点的子树被访问完时的次序序号,这样,当我们每次得到一个v,h时,我们用in[v]和out[v]来标定访问的次序范围,在vector高度为h时进行二分搜索,找到v所在的高度为h的子树,并提取进入该子树和离开该子树时的二进制状态,如果某个二进制状态位为1,说明该字母出现的次数是奇数次。这种字母个数出现次数超过1后,就无法构造回文串。

#include<stdio.h>
#include<iostream>
#include<string>
#include<string.h>
#include<algorithm>
#include<iomanip>
#include<vector>
#include<time.h>
#include<queue>
#include<stack>
#include<iterator>
#include<math.h>
#include<stdlib.h>
#include<limits.h>
#include<map>
#include<set>
//#define ONLINE_JUDGE
#define eps 1e-8
#define INF 0x7fffffff
#define FOR(i,a) for((i)=0;i<(a);(i)++)
#define MEM(a) (memset((a),0,sizeof(a)))
#define sfs(a) scanf("%s",a)
#define sf(a) scanf("%d",&a)
#define sfI(a) scanf("%I64d",&a)
#define pf(a) printf("%d\n",a)
#define pfI(a) printf("%I64d\n",a)
#define pfs(a) printf("%s\n",a)
#define sfd(a,b) scanf("%d%d",&a,&b)
#define sft(a,b,num) scanf("%d%d%d",&a,&b,&num)
#define for1(i,a,b) for(int i=(a);i<b;i++)
#define for2(i,a,b) for(int i=(a);i<=b;i++)
#define for3(i,a,b)for(int i=(b);i>=a;i--)
#define MEM1(a) memset(a,0,sizeof(a))
#define MEM2(a) memset(a,-1,sizeof(a))
#define ll __int64
const double PI=acos(-1.0);
template<class T> T gcd(T a,T b){return b?gcd(b,a%b):a;}
template<class T> T lcm(T a,T b){return a/gcd(a,b)*b;}
template<class T> inline T Min(T a,T b){return a<b?a:b;}
template<class T> inline T Max(T a,T b){return a>b?a:b;}
using namespace std;
//#pragma comment(linker,"/STACK:1024000000,1024000000")
int n,m;
#define M 110
#define N 500010
#define Mod 258280327
#define p(x,y) make_pair(x,y)
char ch[N];
int dth;    //搜索序号
struct Node{
    int dep,val;
    bool operator < (const Node &x) const{
        return dep<x.dep;
    }
    Node(int dep,int val){
        this->dep = dep;
        this->val = val;
    }
};
vector<int> G[N];
int in[N],out[N];   //存储进入点v和离开点v所在子树时的搜索序号
vector<Node>res[N]; //res[i]存储在高度i时的搜索序号和二进制状态
int a[N];
void getLev(int u,int dep){
    in[u] = ++dth;      //进入点u所在子树时的搜索序号
    res[dep].push_back(Node(dth,res[dep][res[dep].size()-1].val^a[u]));
        //存储在高度dep时的搜索序号和二进制的状态,此时它经过了点u,点u的二进制状态为a[u]
    for(int i=0;i<(int)G[u].size();i++){
        int v = G[u][i];
        getLev(v,dep+1);
    }
    out[u] = ++dth;     //离开点u所在子树时的搜索序号
}
int main(){
#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
//  freopen("out.txt", "w", stdout);
#endif
    while(sfd(n,m)!=EOF){
        for(int i=0;i<=n;i++) G[i].clear(),res[i].clear();
        int x;
        for(int i=2;i<=n;i++){
            sf(x);
            G[x].push_back(i);
        }
        sfs(ch+1);
        memset(in,0,sizeof in);
        memset(out,0,sizeof out);
        for(int i=1;i<=n;i++){  //初始化点i的二进制状态表示和高度i的初始高度和状态
            a[i] = 1<<(ch[i]-'a');
            res[i].push_back(Node(0,0));
        }
        dth=0;
        getLev(1,1);    //预处理
        int v,h;
        vector<Node>::iterator l,r;
        while(m--){
            sfd(v,h);
            l = lower_bound(res[h].begin(),res[h].end(),Node(in[v],0)); //>=
            r = upper_bound(res[h].begin(),res[h].end(),Node(out[v],0));    //<
            //二分搜索高度为h且在子树v里面的所有节点的范围
            l--,r--;    //l是子树的开始,即v,题目中说子树包括v,所以我们得--;r是离开子树时的状态,这个状态是不包括的,所以也得--.
            int state = (*l).val^(*r).val; //提取遍历整个v所在的子树后的二进制状态
            int num=0;
            for(int i=0;i<26;i++){
                if(state & (1<<i)) //判断某个字母的出现次数是否为奇数
                    num++;
            }
            if(num>1)
                printf("No\n");
            else
                printf("Yes\n");
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值