bzoj4943 [Noi2017]蚯蚓排队

题面暂缺。。

正解:字符串$hash$。

我在考场上写了个$map$的$hash$被卡成$40$分,然后改成挂链版本的就$AC$了。。$mdzz$,以后$hash$再也不写$map$了。。

我们考虑使用链表来表示字符间的关系,合并和分裂都用链表来表示,这样我们可以快速找到两个字符的前$k$个和后$k$个字符。

注意到每次只会增加或减少$k^{2}$个字符串,那么我们直接把这些字符串$hash$起来即可,查询统计也很简单。

这道题好像是被骂得最惨的一道题??

  1 //It is made by wfj_2048~
  2 #include <algorithm>
  3 #include <iostream>
  4 #include <cstring>
  5 #include <cstdlib>
  6 #include <cstdio>
  7 #include <vector>
  8 #include <cmath>
  9 #include <queue>
 10 #include <stack>
 11 #include <map>
 12 #include <set>
 13 #define rhl (998244353)
 14 #define wyh (19260817)
 15 #define M (10000010)
 16 #define N (300010)
 17 #define il inline
 18 #define RG register
 19 #define ll long long
 20 #define ull unsigned long long
 21
 22 using namespace std;
 23
 24 struct edge{ int nt,sum; ull v; }g[12000010];
 25
 26 int head[wyh+10],a[N],lst[N],nxt[N],st1[60],st2[60],tong[10],n,m,num,fg,top1,top2;
 27 ull hsh[M],bin[M],base=7;
 28 char s[M];
 29 ll ans;
 30
 31 il int gi(){
 32     RG int x=0,q=1; RG char ch=getchar();
 33     while ((ch<‘0‘ || ch>‘9‘) && ch!=‘-‘) ch=getchar();
 34     if (ch==‘-‘) q=-1,ch=getchar();
 35     while (ch>=‘0‘ && ch<=‘9‘) x=x*10+ch-48,ch=getchar();
 36     return q*x;
 37 }
 38
 39 il void insert(RG int from,RG ull to){
 40     g[++num]=(edge){head[from],1,to},head[from]=num; return;
 41 }
 42
 43 il void add(RG ull Hash){
 44     RG int ymd=Hash%wyh;
 45     for (RG int i=head[ymd];i;i=g[i].nt)
 46     if (g[i].v==Hash){ ++g[i].sum; return; }
 47     return insert(ymd,Hash);
 48 }
 49
 50 il void del(RG ull Hash){
 51     RG int ymd=Hash%wyh;
 52     for (RG int i=head[ymd];i;i=g[i].nt)
 53     if (g[i].v==Hash){ --g[i].sum; return; }
 54     return;
 55 }
 56
 57 il ll calc(RG ull Hash){
 58     RG int ymd=Hash%wyh;
 59     for (RG int i=head[ymd];i;i=g[i].nt)
 60     if (g[i].v==Hash) return g[i].sum;
 61     return 0;
 62 }
 63
 64 int main(){
 65 #ifndef ONLINE_JUDGE
 66     freopen("queue.in","r",stdin);
 67     freopen("queue.out","w",stdout);
 68 #endif
 69     n=gi(),m=gi(),fg=1,bin[0]=1;
 70     for (RG int i=1;i<=10000000;++i) bin[i]=bin[i-1]*base;
 71     for (RG int i=1;i<=n;++i){ a[i]=gi(),++tong[a[i]]; if (a[i]!=1) fg=0; }
 72     for (RG int i=1;i<=n;++i) lst[i]=nxt[i]=i;
 73     for (RG int p=1,op,x,y,k,len;p<=m;++p){
 74     op=gi();
 75     if (op==1){
 76         x=gi(),y=gi(),top1=top2=0,st1[++top1]=x,st2[++top2]=y;
 77         for (RG int i=x;top1<49 && lst[i]!=i;i=lst[i]) st1[++top1]=lst[i];
 78         for (RG int i=y;top2<49 && nxt[i]!=i;i=nxt[i]) st2[++top2]=nxt[i];
 79         RG ull Hsh=0; for (RG int i=top1;i;--i) Hsh=Hsh*base+a[st1[i]]; st1[top1+1]=0;
 80         for (RG int i=top1;i;--i){
 81         RG ull Hash=Hsh-a[st1[i+1]]*bin[i]; Hsh=Hash,len=i;
 82         for (RG int j=1;j<=top2;++j){
 83             ++len; if (len>50) break;
 84             Hash=Hash*base+a[st2[j]],add(Hash);
 85         }
 86         }
 87         nxt[x]=y,lst[y]=x;
 88     }
 89     if (op==2){
 90         x=gi(),y=nxt[x],top1=top2=0,st1[++top1]=x,st2[++top2]=y;
 91         for (RG int i=x;top1<49 && lst[i]!=i;i=lst[i]) st1[++top1]=lst[i];
 92         for (RG int i=y;top2<49 && nxt[i]!=i;i=nxt[i]) st2[++top2]=nxt[i];
 93         RG ull Hsh=0; for (RG int i=top1;i;--i) Hsh=Hsh*base+a[st1[i]]; st1[top1+1]=0;
 94         for (RG int i=top1;i;--i){
 95         RG ull Hash=Hsh-a[st1[i+1]]*bin[i]; Hsh=Hash,len=i;
 96         for (RG int j=1;j<=top2;++j){
 97             ++len; if (len>50) break;
 98             Hash=Hash*base+a[st2[j]],del(Hash);
 99         }
100         }
101         nxt[x]=x,lst[y]=y;
102     }
103     if (op==3){
104         scanf("%s",s+1),k=gi(),len=strlen(s+1),ans=1; RG ull Hash;
105         if (k==1){
106         for (RG int i=1;i<=len;++i) ans=ans*(ll)tong[s[i]-48]%rhl;
107         printf("%lld\n",ans); continue;
108         }
109         for (RG int i=1;i<=len;++i) hsh[i]=hsh[i-1]*base+s[i]-48;
110         for (RG int i=1;i+k-1<=len;++i){
111         Hash=hsh[i+k-1]-hsh[i-1]*bin[k];
112         ans=ans*calc(Hash)%rhl;
113         }
114         printf("%lld\n",ans);
115     }
116     }
117     return 0;
118 }
时间: 2024-11-07 04:04:39

bzoj4943 [Noi2017]蚯蚓排队的相关文章

BZOJ4943 &amp; 洛谷3823 &amp; UOJ315:[NOI2017]蚯蚓排队——题解

https://www.lydsy.com/JudgeOnline/problem.php?id=4943 http://uoj.ac/problem/315 https://www.luogu.org/problemnew/show/P3823#sub 题面太长自己看吧orz. 参考:洛谷题解. 用链表暴力维护每个蚯蚓,每次合并和分离只对k*k的元素有影响,哈希一下存起来query时候比较就好了. 没了. (具体复杂度我不会证明,以及bzoj卡空间,正常的哈希表空间总觉得不能开如代码所示的这么

浴谷夏令营题单

这是群里一位神犇整理的,我只负责将它们做完. 一.暴力.搜索Luogu 1588 丢失的牛Luogu 1463 [SDOI2005]反素数antBzoj 1085 [SCOI2005]骑士精神Luogu 1019 单词接龙Luogu 1078 文化之旅Luogu 1312 Mayan游戏Luogu 3823 蚯蚓排队Codeforces 444B Codeforces 555DLuogu 1979 华容道 二.初等数论Poj 3292 H合成数Luogu 1890 gcd区间Luogu 1029

洛谷 P2827 BZOJ 4721 UOJ #264 蚯蚓

题目描述 本题中,我们将用符号表示对c向下取整,例如:. 蛐蛐国最近蚯蚓成灾了!隔壁跳蚤国的跳蚤也拿蚯蚓们没办法,蛐蛐国王只好去请神刀手来帮他们消灭蚯蚓. 蛐蛐国里现在共有n只蚯蚓(n为正整数).每只蚯蚓拥有长度,我们设第i只蚯蚓的长度为,并保证所有的长度都是非负整数(即:可能存在长度为0的蚯蚓). 每一秒,神刀手会在所有的蚯蚓中,准确地找到最长的那一只(如有多个则任选一个)将其切成两半.神刀手切开蚯蚓的位置由常数p(是满足0<p<1的有理数)决定,设这只蚯蚓长度为x,神刀手会将其切成两只长度

【BZOJ4942】[Noi2017]整数 线段树+DFS(卡过)

[BZOJ4942][Noi2017]整数 题目描述去uoj 题解:如果只有加法,那么直接暴力即可...(因为1的数量最多nlogn个) 先考虑加法,比较显然的做法就是将A二进制分解成log位,然后依次更新这log位,如果最高位依然有进位,那么找到最高位后面的第一个0,将中间的所有1变成0,那个0变成1.这个显然要用到线段树,但是复杂度是nlog2n的,肯定过不去. 于是我在考场上yy了一下,这log位是连续的,我们每次都要花费log的时间去修改一个岂不是很浪费?我们可以先在线段树上找到这段区间

【BZOJ4945】[Noi2017]游戏 2-SAT

[BZOJ4945][Noi2017]游戏 题目描述 题解:2-SAT学艺不精啊! 这题一打眼看上去是个3-SAT?哎?3-SAT不是NPC吗?哎?这题x怎么只有8个?暴力走起! 因为x要么不是A要么不是B,所以直接2^8枚举所有x就行了.然后就变成了一个2-SAT问题.假设有两场游戏1,2,分别可以使用的地图为A1,A2,B1,B2,如果有一个限制是1 A 2 A,那么选A1就必须选A2,然后我这个沙茶就开开心心的拿了55分. 为什么不对?我建出来的图显然不对偶啊!考虑逆否命题,选A1就必须选

队列练习--排队买饭

题目描述 中午买饭的人特多,食堂真是太拥挤了,买个饭费劲,理工大的小孩还是很聪明的,直接奔政通超市,哈哈,确实,政通超市里面也卖饭,有好几种菜,做的比食堂好吃多了,价格也不比食堂贵,并且买菜就送豆浆,吸引了不少童鞋.所以有时吧,人还是很多的,排队是免不了的,悲剧的是超市只有两个收银窗口. 问题是这样的:开始有两队人在排队,现在咱们只研究第一队,现在我们给每个人一个编号,保证编号各不相同,排在前面的人买完饭就走了,有些人挑完饭就排在后面等待付款,还有一些人比较聪明,看到另一个队人比较少,直接离开这

NOIP蚯蚓

那么我们开三个不上升队列, 第一个记录原来的蚯蚓, 第二个记录乘以p的蚯蚓 第三个记录乘以(1-p)的蚯蚓, 在记录每条就要入队列的时间,就可以求出增加的长度 每次比较三个队列的队首,取最大的值x的切. 将xp加入第二个队列的队尾 将x(1-p)加入第三个队列的队尾 (第二个第三个队列保证单调,上面证明了) 1 #include<cstdio> 2 #include<algorithm> 3 #include<iostream> 4 #include<cmath&

luogu P1966 火柴排队

二次联通门 : luogu P1966 火柴排队 /* luogu P1966 火柴排队 神TM逆序对... noip怎么这么坑啊.. 暴力都没得打 此题模拟考试时爆了0 做法 将A数组排序,由于B数组与A数组是一一对应的 那么B数组的位置也会发生相应的变化 此时B数组逆序数对数即为答案 */ #include <cstdio> #include <iostream> #include <algorithm> const int BUF = 123123123; cha

【NOIP2013】火柴排队

P1092 - [NOIP2013]火柴排队 Description Input 共三行,第一行包含一个整数 n,表示每盒中火柴的数目. 第二行有 n 个整数,每两个整数之间用一个空格隔开,表示第一列火柴的高度. 第三行有 n 个整数,每两个整数之间用一个空格隔开,表示第二列火柴的高度. Output 输出共一行,包含一个整数,表示最少交换次数对 99,999,997 取模的结果. Sample Input 样例1: 4 2 3 1 4 3 2 1 4 样例2: 4 1 3 4 2 1 7 2