题解 | #Link with Checksum#

The Game of Eating

https://ac.nowcoder.com/acm/contest/57356/D

alt

嘤嘤菜菜,大佬带带,呜呜。

这场只会三个题,随便写写。是摸鱼的嘤嘤捏,今天代码行数似乎不到三位数呢~~~

D The Game of Eating

心机题!建议不要跟出题人一起吃饭!(除非他请我吃饭)

贪心,博弈。

首先,令 t=mk+1t=m-k+1 ,也就是最后一个人可以选择的菜的数量。

最后一个人一定会在 tt 个菜中选他最喜欢的菜,那么,倒数第二个人在 t+1t+1 个菜中,可以把最后一个人最喜欢的菜留给最后一个人点,然后他点剩下 tt 个菜中最喜欢的菜。那么,倒数第三个人也可以这样做………………

以此类推,最后一个人一定会点到他最喜欢的菜,因为所有人都会把这道菜让给他来点,倒二个人一定会点到其他菜中他最喜欢的菜,因为他前面的人都会把这道菜让给他来点………………

那么,从后往前,每次选择这个人最喜欢的菜,然后去掉这道菜,就是答案。由于一个人对所有菜的喜爱值都不同,所以答案唯一。

#include<bits/stdc++.h>

using namespace std;

using LL = long long;

int main(){
    int T;
    cin>>T;
    while(T--){
        int n,m,k;
        cin>>n>>m>>k;
        vector a(n+1,vector<int>(m+1));
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                cin>>a[i][j];
            }
        }
        vector<int> v;
        for(;k>0;k--){
            int t = k % n;
            if(!t) t = n;
            auto j = max_element(a[t].begin(), a[t].end()) - a[t].begin();
            v.push_back(j);
            for(int i=1;i<=n;i++){
                a[i][j] = 0;
            }
        }
        sort(v.begin(),v.end());
        for(auto &i : v){
            cout<<i<<" ";
        }
        cout<<endl;
    }
}
//30行

G Link with Centrally Symmetric Strings

马拉车、贪心

队友:马拉车!

嘤嘤:让我康康!

板子随便改了改,写了个equal函数,然后贪心一下,再debug半天,就过了。可惜debug慢了点,只拿了个二血,好气哦,东大能不能学学jiangly单挑啊,哼。

要注意,长度为奇数的串中间那个字母必须中心对称,然后如果初始字符串有其他字母,直接寄。之后每次询问区间 llrr 是否是中心对称, lrl,r 初始都是1, rr 每次都加一,然后找到中心对称后, ll 就变成 r+1r+1 ,否则 ll 不变,若最后 rr 大于字符串长度,则yes,否则no。

#include<bits/stdc++.h>
#define endl '\n'

using namespace std;

struct Manacher{
	string s;			//原串
	int n;				//str的size
	string str;			//补充后的字符串
	vector<int> len;	//回文半径
	Manacher(string s) : s(s),n(s.size()*2+3){
		init(str);
		build(len);
	}
	void init(string &str){
		str="$#";
		for(auto &i : s){
			str+=i;
			str+='#';
		}
		str+='@';
	}
	void build(vector<int> &len){
    // 写12行 + 改3行 = 15行
        auto equ = [&](char l,char r){
            if(l=='#' && r=='#') return 1;
            if(l=='o' || l=='s' || l=='x' || l=='z'){
                if(l==r) return 1;
                else return 0;
            }
            if(l>r) swap(l,r);
            if(l=='b' && r=='q') return 1;
            if(l=='d' && r=='p') return 1;
            if(l=='n' && r=='u') return 1;
            return 0;
        };
		len=vector<int>(n,0);
		int l=1 , r=1 , p=1;
		for(int i=2;i<=n-3;i++){
            if(!equ(str[i],str[i])) continue;
			if(i>r){
				l = r = p = i;
				while(equ(str[l-1],str[r+1]))
					l--,r++;
				len[i] = r - p;
			}
			else{
				len[i] = len[2*p-i];
				if(i+len[i]>=r){
					p = i;
					l = 2 * p - r;
					while(equ(str[l-1],str[r+1]))
						l--,r++;
					len[i] = r - p;
				}
			}
		}
	}
};

int main(){
    ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    int T;
    cin>>T;
    map<int,int> mp;
    mp['o']++;
    mp['s']++;
    mp['x']++;
    mp['z']++;
    mp['b']++;
    mp['q']++;
    mp['d']++;
    mp['p']++;
    mp['n']++;
    mp['u']++;
    while(T--){
        string s;
        cin>>s;
        Manacher ma(s);
        int n = s.size();
        int j = 1;
        for(auto &i : s){
            if(!mp.count(i)){
                goto no;
            }
        }
        for(int i=1;i<=n;i++){
            int t = i - j + 1;
            if(ma.len[i+j]>=t) j = i + 1;
        }
        if(j>n) cout<<"Yes"<<endl;
        else goto no;
        if(0) no: cout<<"No"<<endl;
    }
	return 0;
}
//30(包括mp[]++) + 15 = 45

H 0 and 1 in BIT

线段树

其实可以不用线段树,前缀和乱搞一下就可以了,但是把线段树丢给队友写,就可以不用脑子了呢~~(诶嘿)

观察样例可得,字符串为0011,ABAB操作后不变,分解一下操作,只看ABA,答案是0010,会发现,其实就是原本减一。再试试ABBA,答案是0001,会发现,就是原本减二。而A操作会让字符串取反,那么A的个数已经不重要了,只需要考虑有奇数个还是偶数个A。那么,接下来是化简,以ABBABBBABB为例,转化一下,也就是【-2,+3,-2】,因此,只需要 -1 即可,共有三个A,是奇数,需要将字符串翻转,答案为1101。尝试验证一下,答案正确。

接下来是进位和退位,字符串长度为50,那么long long完全可以存的下,转化成整数后,1111进位时会变成000...10000,只考虑最后四位,答案是正确的。如果是负数,0000退位时,也会变成111....11111(补码),若是不会补码,或者担心出现问题,那么只要加上2的60次方,就可以保证操作永远在正数范围内。(000...001000...001111)

此时,我们只需要查出操作的大小,以及是否要翻转,剩余的就是字符串与数字之间的转换了,难度骤降。

好,本题到此结束。

什么?你说你不会查询?让队友写个线段树不就好了?

什么?队友也不会?那我也不会啊,我也妹写线段树啊,我就写了个大暴力啊~

口胡一下前缀和:维护一个从头到这里的操作次数是多少,再维护一个从头到这里有几个A,然后查询的时候前乱搞一下,再看看符号就好了。

#include <bits/stdc++.h>
#define endl '\n'
using namespace std;
using LL = long long;
using PII = pair<int, int>;

#define lson (k << 1)
#define rson (k << 1 | 1)

const int N = 3 + 2e5;

struct TreeNode {
    int l, r;
    int a, b;
} tr[N << 2];

char s[N];
int n, q;

void up(TreeNode &rt, TreeNode l, TreeNode r) {
    rt.a = l.a + r.a;
    rt.b = l.b;
    if (l.a % 2) {
        rt.b -= r.b;
    } else {
        rt.b += r.b;
    }
}

void build(int k, int l, int r) {
    tr[k].l = l;
    tr[k].r = r;
    if (l == r) {
        if (s[r] == 'A') {
            ++tr[k].a;
        } else {
            ++tr[k].b;
        }
        return;
    }
    int mid = l + r >> 1;
    build(lson, l, mid);
    build(rson, mid + 1, r);
    up(tr[k], tr[lson], tr[rson]);
}

TreeNode query(int k, int l, int r) {
   // cout << k << ' ' << l << ' ' << r << endl;
    if (l <= tr[k].l && tr[k].r <= r) {
        return tr[k];
    }
    int mid = tr[k].l + tr[k].r >> 1;
    if (l <= mid && mid < r) {
        TreeNode ans;
        up(ans, query(lson, l, r), query(rson, l, r));
        return ans;
    }
    if (l <= mid) {
        return query(lson, l, r);
    } else {
        return query(rson, l, r);
    }
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cin >> n >> q;
    cin >> s + 1;

    build(1, 1, n);
    
    LL ans = 0;
    while (q--) {
        int l, r;
        string x;
        cin >> l >> r >> x;
        int reall = min((ans ^ l) % n + 1, (ans ^ r) % n + 1);
        int realr = max((ans ^ l) % n + 1, (ans ^ r) % n + 1);
        l = reall;
        r = realr;
        auto tno = query(1, l, r);
        auto a = tno.a;
        auto b = tno.b;
        ans = 1ll<<60;
        int n = x.size();
        for(int i=0;i<n;i++){
            if(x[i]=='1') ans += 1ll<<(n-i-1);
        }
        ans += b;
        string s;
        for(int i=0;i<n;i++){
            s += ((ans>>i)&1) + '0';
        }
        if(a&1){
            for(auto &i : s){
                i ^= 1;
            }
        }
        ans = 0;
        reverse(s.begin(),s.end());
        for(auto &i : s){
            ans *= 2;
            ans += i&1;
        }
        cout<<s<<endl;
    }
    return 0;
}
//25行

30+45+25,好像差不多刚好100捏,还生产了一堆废物代码捏~~ 下一场也要继续开摆呢

全部评论

相关推荐

10-17 10:05
已编辑
北华大学 全栈开发
牛客872465272号:掉头发了哥
点赞 评论 收藏
分享
不愿透露姓名的神秘牛友
10-12 10:48
已编辑
秋招之苟:邻居家老哥19届双2硕大厂开发offer拿遍了,前几天向他请教秋招,他给我看他当年的简历,0实习实验室项目技术栈跟开发基本不沾边😂,我跟他说这个放在现在中厂简历都过不了
点赞 评论 收藏
分享
24 1 评论
分享
牛客网
牛客企业服务