首页 > 其他分享 >冲刺国赛模拟 38

冲刺国赛模拟 38

时间:2023-07-18 15:36:23浏览次数:33  
标签:38 int mid 冲刺 -- 600010 国赛 include id

我球球你们不要到处转发我博客点踩了。这玩意已经超过yspm峰值了,这就是钓鱼的动力吗。还没踩过的赶紧去踩一下。然而 yspm 的强大之处在于每天都能保证 5-20 个踩不等,不得不说非常厉害。

二次整数规划在写了,估计今天晚上能写完。求求你们不要让我写树上邻域数点。我是不是学 yspm 把踩隐藏了可以减少一部分的踩数。

智力游戏

确实挺智力的。NOI 前最后一场模拟赛考普及 bfs。

#include <iostream>
#include <algorithm>
#include <algorithm>
#include <cstring>
#include <vector>
#include <map>
#include <queue>
using namespace std;
typedef unsigned long long ull;
const ull prm=131;
int mx;
struct node{
    int p;
    char od;
    int x;
};
map<ull,int>mp;
struct gra{
    int s[10][10];
    vector<node>ans;
    ull hs(){
        ull hs=0;
        for(int i=1;i<=6;i++)for(int j=1;j<=6;j++)hs=hs*prm+(s[i][j]+'0');
        return hs;
    }
}tmp;
queue<gra>q;
gra bfs(){
    int hs=0;
    q.push(tmp);mp[tmp.hs()]=1;
    while(!q.empty()){
        gra u=q.front();q.pop();
        if(u.s[3][5]==1&&u.s[3][6]==1)return u;
        for(int x=1;x<=mx;x++){
            int x1=7,y1=7,x2=0,y2=0;
            for(int i=1;i<=6;i++){
                for(int j=1;j<=6;j++){
                    if(u.s[i][j]==x){
                        x1=min(x1,i);y1=min(y1,j);x2=max(x2,i);y2=max(y2,j);
                    }
                }
            }
            if(x1==x2){
                tmp=u;
                int dy=y1,ddy=y2;
                for(int d=1;d<=6;d++){
                    dy--;
                    if(tmp.s[x1][dy]!=0)break;
                    tmp.s[x1][dy]=x;tmp.s[x1][ddy]=0;
                    ddy--;
                    ull hs=tmp.hs();
                    if(mp.find(hs)!=mp.end())continue;
                    mp[hs]=1;
                    tmp.ans.push_back({x,'L',d});
                    q.push(tmp);
                    tmp.ans.pop_back();
                }
                tmp=u;
                dy=y2,ddy=y1;
                for(int d=1;d<=6;d++){
                    dy++;
                    if(tmp.s[x1][dy]!=0)break;
                    tmp.s[x1][dy]=x;tmp.s[x1][ddy]=0;
                    ddy++;
                    ull hs=tmp.hs();
                    if(mp.find(hs)!=mp.end())continue;
                    mp[hs]=1;
                    tmp.ans.push_back({x,'R',d});
                    q.push(tmp);
                    tmp.ans.pop_back();
                }
            }
            else{
                tmp=u;
                int dx=x1,ddx=x2;
                for(int d=1;d<=6;d++){
                    dx--;
                    if(tmp.s[dx][y1]!=0)break;
                    tmp.s[dx][y1]=x;tmp.s[ddx][y1]=0;
                    ddx--;
                    ull hs=tmp.hs();
                    if(mp.find(hs)!=mp.end())continue;
                    mp[hs]=1;
                    tmp.ans.push_back({x,'U',d});
                    q.push(tmp);
                    tmp.ans.pop_back();
                }
                tmp=u;
                dx=x2,ddx=x1;
                for(int d=1;d<=6;d++){
                    dx++;
                    if(tmp.s[dx][y1]!=0)break;
                    tmp.s[dx][y1]=x;tmp.s[ddx][y1]=0;
                    ddx++;
                    ull hs=tmp.hs();
                    if(mp.find(hs)!=mp.end())continue;
                    mp[hs]=1;
                    tmp.ans.push_back({x,'D',d});
                    q.push(tmp);
                    tmp.ans.pop_back();
                }
            }
        }
    }
    return tmp;
}
int main(){
    memset(tmp.s,-1,sizeof(tmp.s));
    for(int i=1;i<=6;i++){
        for(int j=1;j<=6;j++){
            scanf("%d",&tmp.s[i][j]);
            mx=max(mx,tmp.s[i][j]);
        }
    }
    vector<node>ans=bfs().ans;
    printf("%d\n",(int)ans.size());
    for(node x:ans)printf("%d %c %d\n",x.p,x.od,x.x);
    return 0;
}

区域划分

挺智慧的。

能够猜到的结论是只要没有相同元素相邻且三种元素都出现就有解,否则无解。证明题解说可以归纳,这结论我确实是猜的,然而并不会构造于是冲了一发区间 dp。

考虑构造。用 \(0\) 划分出所有段,即 \(012121212012121212\cdots\) 这样的东西。对于相邻的两端,若一个 \(1\) 一个 \(2\) 那直接连起来没问题。现在 \(0\) 左右都是一个数,假设是 \(1\)。那么对于所有的 \(0\),把它和前面第一个 \(2\) 连起来,并把后边第一个 \(1\) 和这个 \(2\) 也连起来就可以把这样的段合并起来。现在只有一个段了,随便连一下就好了。

#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
using namespace std;
int n,a[100010],cnt[3],pre[100010],nxt[100010];
void del(int x){
    pre[nxt[x]]=pre[x];
    nxt[pre[x]]=nxt[x];
}
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%d",&a[i]),pre[i]=i-1,nxt[i]=i+1;
    pre[1]=n,nxt[n]=1;
    for(int i=1;i<=n;i++){
        if(a[i]==a[nxt[i]]){
            puts("No");return 0;
        }
        cnt[a[i]]++;
    }
    if(!cnt[0]||!cnt[1]||!cnt[2]){
        puts("No");return 0;
    }
    puts("Yes");
    for(int i=1;i<=n;i++){
        if(a[i]==0){
            if(a[pre[i]]+a[nxt[i]]==3&&--cnt[0]){
                printf("%d %d\n",pre[i],nxt[i]);del(i);
            }
        }
    }
    for(int i=1;i<=n;i=nxt[i]){
        if(a[i]==0&&a[nxt[i]]+a[nxt[nxt[i]]]==3){
            for(int j=nxt[nxt[nxt[i]]];j!=i;j=nxt[j]){
                if(a[j]==0){
                    printf("%d %d\n",pre[pre[j]],j);
                    printf("%d %d\n",pre[pre[j]],nxt[j]);
                    del(pre[j]);del(j);
                }
            }
            for(int j=nxt[nxt[i]];nxt[j]!=i;j=nxt[j]){
                printf("%d %d\n",i,j);
            }
            return 0;
        }
    }
    return 0;
}

基因识别

冲个带修莫队冲过 6e5,我不好说是数据水了还是卡不满。

在 SA 上二分出每个串对应的区间,跑带修莫队即可,复杂度 \(O(n^{\frac 53})\),然而可以跑过,我也很震撼。甚至题解都是这个东西。

更好的做法是根号分治,但是我不会。

#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <vector>
#include <cmath>
#define int long long
using namespace std;
int n,tot,m,sq,a[600010];
char s[600010],t[600010];
int sa[600010],rk[600010],cnt[600010],rk2[600010],id[600010],key[600010];
void getsa(){
    int m=127;
    for(int i=1;i<=n;i++){
        rk[i]=s[i];cnt[rk[i]]++;
    }
    for(int i=1;i<=m;i++)cnt[i]+=cnt[i-1];
    for(int i=n;i>=1;i--)sa[cnt[rk[i]]--]=i;
    for(int w=1;;w<<=1){
        int p=0;
        for(int i=n;i>n-w;i--)id[++p]=i;
        for(int i=1;i<=n;i++)if(sa[i]>w)id[++p]=sa[i]-w;
        for(int i=1;i<=m;i++)cnt[i]=0;
        for(int i=1;i<=n;i++)key[i]=rk[id[i]],cnt[key[i]]++;
        for(int i=1;i<=m;i++)cnt[i]+=cnt[i-1];
        for(int i=n;i>=1;i--)sa[cnt[key[i]]--]=id[i];
        for(int i=1;i<=n;i++)rk2[i]=rk[i];
        p=0;
        for(int i=1;i<=n;i++){
            if(rk2[sa[i]]==rk2[sa[i-1]]&&rk2[sa[i]+w]==rk2[sa[i-1]+w])rk[sa[i]]=p;
            else rk[sa[i]]=++p;
        }
        if(p==n){
            for(int i=1;i<=n;i++)sa[rk[i]]=i;break;
        }
        m=p;
    }
}
int val[600010],belong[600010];
int check(char t[],int pos){
    int len=strlen(t+1);
    for(int i=1;i<=len;i++){
        if(s[pos+i-1]>t[i])return 1;
        if(s[pos+i-1]<t[i])return -1;
    }
    return 0;
}
int getl(char t[]){
    int l=0,r=n+1;
    while(l<r){
        int mid=(l+r)>>1;
        if(check(t,sa[mid])>=0)r=mid;
        else l=mid+1;
    }
    return l;
}
int getr(char t[]){
    int l=0,r=n+1;
    while(l<r){
        int mid=(l+r+1)>>1;
        if(check(t,sa[mid])>0)r=mid-1;
        else l=mid;
    }
    return l;
}
bool JUD;
struct ques{
    int l,r,t,id;
	bool operator<(const ques& s)const{
        if(!JUD){
            if(l/sq!=s.l/sq)return l<s.l;
            return r<s.r;
        }
        else{
            if(l/sq!=s.l/sq)return l<s.l;
            if(r/sq!=s.r/sq)return r<s.r;
            return t<s.t;
        }
	}
}q[600010];
struct node{
    int x,val;
}upd[600010];
int sum,num[600010],ans[600010];
void add(int x){
    if(!num[x])sum+=val[x];
    num[x]++;
}
void del(int x){
    num[x]--;
    if(!num[x])sum-=val[x];
}
void update(int t){
    if(num[upd[t].x])sum+=upd[t].val;
    val[upd[t].x]+=upd[t].val;
}
void modify(int t){
    if(num[upd[t].x])sum-=upd[t].val;
    val[upd[t].x]-=upd[t].val;
}
signed main(){
    scanf("%lld%lld",&tot,&m);
    for(int i=1;i<=tot;i++){
        scanf("%lld%s",&val[i],t+1);
        int len=strlen(t+1);
        for(int j=1;j<=len;j++)s[++n]=t[j],belong[n]=i;
        s[++n]='z'+1;
    }
    getsa();
    for(int i=1;i<=n;i++)a[i]=belong[sa[i]];
    int T=0,cnt=0;
    for(int i=1;i<=m;i++){
        int od;scanf("%lld",&od);
        if(od==1){
            scanf("%s",t+1);
            int l=getl(t),r=getr(t);cnt++;
            q[cnt]={l,r,T,cnt};
        }
        else{
            int x,y;scanf("%lld%lld",&x,&y);
            T++;upd[T]={x,y};
        }
    }
    if(!T){
        sq=pow(n,0.5);
    }
    else{
        sq=pow(n,2.0/3);JUD=true;
    }
    sort(q+1,q+cnt+1);
    for(int i=1,l=1,r=0,t=0;i<=cnt;i++){
		while(l>q[i].l)add(a[--l]);
		while(r<q[i].r)add(a[++r]);
		while(l<q[i].l)del(a[l++]);
		while(r>q[i].r)del(a[r--]);
		while(t<q[i].t)update(++t);
		while(t>q[i].t)modify(t--);
		ans[q[i].id]=sum;
	}
	for(int i=1;i<=cnt;i++)printf("%lld\n",ans[i]);
	return 0;
}

标签:38,int,mid,冲刺,--,600010,国赛,include,id
From: https://www.cnblogs.com/gtm1514/p/17563143.html

相关文章

  • 题解 P5384
    这题有紫??对于询问节点\(u\),倍增地跳到它的\(k\)级祖先,求其子树内有多少深度为\(dep_u\)的节点。我们考虑把询问离线,再通过dfs序把树拍平,然后扫一遍直接求就行了。复杂度\(O(n\logn)\)。code:#include<bits/stdc++.h>usingnamespacestd;constintN=1e6+5;inlin......
  • 题解 P3806
    点分治模板题。点分治适合处理大规模的树上路径信息问题暴力做法:dfs每个点\(u\),算出其子树内每个点到\(u\)的距离,统计经过\(u\)的所有路径,复杂度\(O(n^2)\)。容易发现,复杂度和子树大小有关。对于当前子树,我们可以求出其重心,计算经过重心的所有路径,删掉重心,递归每个联通......
  • 题解 P8338 [AHOI2022] 排列
    恶心题。每次操作,相当与把第\(i\)个数置换到\(p_i\),于是可以连边。因为\(i\)和\(p_i\)互不相同,所以对于每一个点,有且仅有一条出边和一条入边,即若干个简单环。那么最少操作\(\operatorname{lcm}(a_1,a_2,a_3...a_{x-2},a_{x-1},a_x)\)次点会都回到原位。其中\(a_i\)......
  • 题解 P3803 【模板】多项式乘法(FFT)
    感觉题解区不是写的太高深,就是写的太高深。所以给初中、小学和幼儿园的萌新准备一篇简单易懂的良心题解~前置知识一、多项式的系数表示法和点值表示法。\(A(x)=\sum\limits_{i=0}^{n-1}a_i\cdotx^i\)系数:\((a_0,a_1,a_2...a_{n-2},a_{n-1})\)。点值:\((x_0,y_0),(x_1,y_1)...(......
  • 洛谷 Luogu P1038 [NOIP2003 提高组] 神经网络
    这题看着很吓人实则很简单。求输出层,正着求很麻烦,因为知不道谁连向这个点,所以可以反向建边,反着求。拓扑+dfs,时间复杂度\(\text{O(n+m)}\)#include<iostream>#include<cstdio>#include<queue>#defineN105#defineM(N*N/2+114)structE{intv,w;......
  • 【雕爷学编程】Arduino动手做(06)---KY-038声音传感器模块4
    37款传感器与执行器的提法,在网络上广泛流传,其实Arduino能够兼容的传感器模块肯定是不止这37种的。鉴于本人手头积累了一些传感器和执行器模块,依照实践出真知(一定要动手做)的理念,以学习和交流为目的,这里准备逐一动手尝试系列实验,不管成功(程序走通)与否,都会记录下来—小小的进步或是搞......
  • 【雕爷学编程】Arduino动手做(06)---KY-038声音传感器模块2
    37款传感器与执行器的提法,在网络上广泛流传,其实Arduino能够兼容的传感器模块肯定是不止这37种的。鉴于本人手头积累了一些传感器和执行器模块,依照实践出真知(一定要动手做)的理念,以学习和交流为目的,这里准备逐一动手尝试系列实验,不管成功(程序走通)与否,都会记录下来—小小的进步或是搞......
  • 2023冲刺国赛模拟 36.1
    最近越来越懒了,估了很长时间的题解,OI生涯结束前是凑不够200篇博客了,但退役前还是努力写点东西吧。第一次写题解的大约在暑假集训,原因是当时改模拟赛题目经常参考学长的博客,于是自己也尝试这写了博客;然而省选以后,改题就很少参考学长的博客,一个原因是很难找到模拟赛题目的题解,......
  • 【考后总结】7 月多校国赛模拟赛 3
    7.14冲刺国赛模拟36T1染色题关键性质是奇数偶数位上可以放置的只有两种,若\(i\)和\(i-2\)选的颜色不同,那么在\(i\)位置放一个球,\([l,r]\)的限制等价于\([l+2,r]\)中奇数位和偶数位不同时有球。设\(f_i\)为\(i\)放置一个球的合法方案数,这样直接枚举上一个球所在......
  • 冲刺国赛模拟 36
    感觉思想都不难,但是场上不是想不出来就是写不动,见了鬼了。染色题考虑一个转化:对于奇数位置,在\(a_i\neqa_{i+2}\)的地方放一个红球,对于偶数位置在同样的地方放个蓝球。这样每个区间的限制变成\([l,r-2]\)不能同时有红蓝球,转移前缀和优化一下即可。#include<iostream>#inc......