[考试反思]0122省选模拟12:延迟

博客咕过了一年我也就忘了我考试状态了2333。

T1是弱智题但是没想。。。写个暴力跑路了(时间不够,主要投在T2/3上了)

然而其实想到了一个乱搞,觉得能得分的概率不大,结果数据奇水完全不对的玩意还有20分,然而我并没有写。。。

然而T2写的是正解,虽说没有其他人的状压优秀,T了一个细节WA了一个拿了80分,凑合吧。

然后T3时间不多的时候写的,拿个暴力,想到了正解大概怎么写但是没有写,太恶心。

考后改题写了写,一下午就过去了。。。一晚上也就过去了。。。弄得跟我颓废了半天一样。。。

然而是真xx难写啊越写越自闭。

考试状态还行。考后改题心态崩了(?)

T1:Colorado Potato Beetle

大意:一个人走,给定路径求它包住的面积。步长$10^6$,步数$n \le 1000$

离散化+BFS。考场上想的太复杂了。白送分不要。。。

按照直觉写,写出来就差不多了。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int n,d[1111],x[11111111],y[11111111],xc,yc,nt[6666][6666],qx[66666666],qy[66666666];
 4 char s[1111][4];long long ans;
 5 map<int,int>X,Y;
 6 int main(){
 7     cin>>n;int nx=0,ny=0,tx,ty,fx,fy;
 8     X[0];X[1];X[-1];Y[1];Y[0];Y[-1];
 9     for(int i=1;i<=n;++i){
10         scanf("%s%d",s[i],&d[i]);
11         if(s[i][0]==‘U‘)nx-=d[i];
12         if(s[i][0]==‘D‘)nx+=d[i];
13         if(s[i][0]==‘L‘)ny-=d[i];
14         if(s[i][0]==‘R‘)ny+=d[i];
15         X[nx];X[nx-1];X[nx+1];
16         Y[ny];Y[ny-1];Y[ny+1];
17     }
18     for(auto I:X)x[++xc]=I.first;
19     for(auto I:Y)y[++yc]=I.first;
20     for(int i=1;i<=xc;++i)X[x[i]]=i;
21     for(int i=1;i<=yc;++i)Y[y[i]]=i;
22     x[++xc]=y[++yc]=1000000007;
23     nx=0,ny=0;
24     for(int i=1;i<=n;++i){
25         fx=X[nx];fy=Y[ny];
26         if(s[i][0]==‘U‘)nx-=d[i];
27         if(s[i][0]==‘D‘)nx+=d[i];
28         if(s[i][0]==‘L‘)ny-=d[i];
29         if(s[i][0]==‘R‘)ny+=d[i];
30         tx=X[nx];ty=Y[ny];
31         if(fx>tx||fy>ty)swap(fx,tx),swap(fy,ty);
32         for(int i=fx;i<=tx;++i)for(int j=fy;j<=ty;++j)nt[i][j]=1;
33     }
34     qx[1]=qy[1]=1;ans=(0ll+x[xc]-x[1])*(y[yc]-y[1]);
35     for(int i=1;i<=xc;++i)nt[i][0]=nt[i][yc]=1;
36     for(int i=1;i<=yc;++i)nt[0][i]=nt[xc][i]=1;
37     for(int h=1,t=1;h<=t;++h){
38         int xx=qx[h],yy=qy[h];
39         if(nt[xx][yy])continue;
40         nt[xx][yy]=1;ans-=(0ll+x[xx+1]-x[xx])*(y[yy+1]-y[yy]);
41         qx[++t]=xx+1;qy[t]=yy;
42         qx[++t]=xx-1;qy[t]=yy;
43         qx[++t]=xx;qy[t]=yy+1;
44         qx[++t]=xx;qy[t]=yy-1;
45     }cout<<ans<<endl;
46 }

T2:Distinct Paths

大意:$n \times m$矩阵上填$k$种颜色,有些格子已经填好,要求任意一条长度为$n+m-1$的$(1,1)$到$(n,m)$的序列上所有颜色都不能相同求方案数。$n,m \le 1000,k \le 10$

数据范围唬人,然而显然如果$n+m-1 > k$答案一定是0。所以就没那么多想法。

搜索,记搜,压状态,11进制的,每一位表示这种颜色出现过的最右位置是第几列,根据这个状态就能确定这一位能不能填某种颜色。

加个剪枝卡卡常,然后开心搜就行。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 unordered_map<long long,int>M[12][12];
 4 #define mod 1000000007
 5 int mo(int x){return x>=mod?x-mod:x;}
 6 long long chg(long long st,int p,int v){p--;return st^(st&15ll<<(p<<2))^(1ll*v<<(p<<2));}
 7 int n,m,k,lp[12][12][12],ac[12][12],ok[12][12][12];
 8 int sch(int x,int y,long long st){
 9     if(x==n&&y==m+1)return 1;
10     if(y==m+1)x++,y=1;
11     if(M[x][y][st])return M[x][y][st];
12     long long rs=st;
13     for(int i=1;i<=k;++i)lp[x][y][i]=rs&15,rs>>=4;
14     if(ac[x][y])return M[x][y][st]=lp[x][y][ac[x][y]]<=y?0:sch(x,y+1,chg(st,ac[x][y],y));
15     int ans=0,cnt15=0,tp=1;
16     for(int i=1;i<=k;++i)if(!ok[x][y][i])if(lp[x][y][i]>y&&lp[x][y][i]!=15)ans=mo(ans+sch(x,y+1,chg(st,i,y)));else if(lp[x][y][i]==15)cnt15++,tp=i;
17     if(cnt15)ans=(ans+cnt15*1ll*sch(x,y+1,chg(st,tp,y)))%mod;
18     return M[x][y][st]=ans;
19 }
20 int main(){
21     cin>>n>>m>>k;
22     if(n+m-1>k)return puts("0"),0;
23     for(int i=1;i<=n;++i)for(int j=1;j<=m;++j){
24         cin>>ac[i][j];
25         for(int x=1;x<=i;++x)for(int y=1;y<=j;++y)ok[x][y][ac[i][j]]=1;
26         ok[i][j][ac[i][j]]=0;
27     }
28     long long prest=(1ll<<(k<<2))-1;
29     for(int i=1;i<=n;++i)for(int j=1;j<=m;++j)if(ac[i][j])prest=chg(prest,ac[i][j],14);
30     cout<<sch(1,1,prest)<<endl;
31 }

T3:回忆树

大意:给定trie,每次询问一条路径上某个字符串出现多少次。$n,m \le 100000, \sum |S| \ le 300000$

很恶心的大神题。思路不是很难想但是真的不好码。

首先直接找出路径然后询问复杂度肯定升天了,但是不难发现其实带拐弯的询问能拆成比较好做的几部分

首先是一条上来的链,然后是以拐点为中心的两侧长各为$|S|-1$的链,然后又是一条下去的链。

跨过拐点的部分看似和原问题是一样的,但是因为总询问串长不大,所以做暴力的话复杂度也是对的(哈希或kmp)。

只要能在合法的复杂度之内找到两点到lca路径上的某一段就可以。倍增然后暴力跳父亲,复杂度肯定没问题。

现在就剩两条链的事了。因为询问是有方向的,所以上下两条链貌似不一样,但是其实只要在处理上来的那条链的时候把询问串翻转一下就和下去的那条链一样。现在问题就是考虑怎么弄一条链。

这样其实就是很经典的字符串匹配,但是是树上的多条链和多个模式串进行匹配,怎么做?

直观上有两个想法:

1)树上字符串,广义SAM直接来啊:

  这也是我考场上想到的,但是直接放弃了。

  利用endpos集合的含义,其实问题就转变成了求一个字符串在广义SAM上匹配之后,有多少个endpos在指定链上。

  这个想法看起来简单粗暴直接好理解,但是细思极恐。

  按照之前那些题的套路,树上维护endpos,那不就是线段树合并了吗。。?

  然后这个东西问的还是链上的,所以要快速求和,再写个树链剖分呗。。。

  这么多硬菜加在一起,轻轻松松4k起步,写出来也要调到暴毙。。。

  然后我果断没有写这个因为估计考场上写不完。考后又在寻找更简单一点的方法。

2)没有花哨的字符串多串匹配当然首选AC自动机啊:

  可能是太久没用到了所以有些生疏。还回头看了看板子(虽说自己默写的其实没错)

  对于已经给定的那个trie建AC自动机并没有什么用。因为它又不是模式串。

  模式串是询问里的那些啊。。。然而居然没有强制在线?那不好说?离线下来建个AC自动机呗。。。

  (然而别忘了因为要处理向上的链,所以反串也要塞进AC自动机里。。)

  树上匹配字符串在AC自动机上跑也没问题啊,直接来就行。

  但是是链上,咋整?这个链已经被转化成了一个点到根的路径的一部分了。

  到根上的好求啊,直接从根开始匹配然后dfs前缀和累加就好了啊。

  那么到根的路径的一部分其实就是两个到根的路径做差呗。。。经典的差分思路。

  然而看一下我们要询问的是啥?某个串出现次数。也就是在原trie祖先链上每个节点对应的AC自动机上节点在当前节点对应的AC自动机节点的子树内的出现次数和。

  单点加。询问子树和。

  第一想法是LCT。当场暴毙。

  哪里有那么麻烦,直接拍在dfn序上,单点加就单点加,子树求和就是查区间。

  树状数组维护。这有何难?

  差分什么的拿vector存一下然后放在trie上dfs跑就好了。进这个点时加上AC自动机对应点的贡献,回溯时再删掉。

  但是要注意这个差分,例如对于u-lca,并不能简单的在u加在lca减。因为在lca处及靠下一点的部分其实与更靠上的节点也产生了贡献。

  例如:1a2a3a4a5b6a7a8a9b10a11a12a13a14a15。查询7-15上aa出现次数。

  7和15的lca是7啊。然而如果你在7处减的话你会把6a7a8这个给算上。(这东西在8节点产生的贡献没有在7被扣掉)

  这里写错直接爆零。。。手模了好多小样例都不错,被这玩意卡了一下调了好久。。。

  (然而找样例用了一个小时改正也就十几分钟。。。当我发现这个能卡我的样例时高兴坏了)

  所以应该是在lca向u走len-1步之后的那个节点减去贡献。

  在写暴力的时候顺便把这个加进去就好了,因为经过lca的那段的暴力哈希当然也要用到这个节点。

  然后想偷懒的我选择了这个方法,在仔细思考之后发现哈希+树状数组+倍增lca/暴跳+若干dfs貌似代码也不会好到哪里去。。。

  于是暴写一下午+半晚上写出了这个难得一见的80+行的代码。

  因为没写完被认为在颓废还被查了几次水表。。。自闭。。。

  终于在大半夜AC了这道题。写个博客题解当解题报告。算是比较圆满的结束了这一天。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define S 666666
 4 int n,m,c[26][S],f[S],fir[S],l[S],to[S],v[S],ec,ch[S],pc,rt;
 5 int R[S],q[S],ans[S],F[20][S],dep[S],fv[S];char s[S];
 6 vector<int>ap[S],Rt[S];
 7 void link(int a,int b,int va){l[++ec]=fir[a];fir[a]=ec;to[ec]=b;v[ec]=va;}
 8 void DFS(int p){
 9     dep[p]=dep[F[0][p]]+1;for(int i=1;i<19;++i)F[i][p]=F[i-1][F[i-1][p]];
10     for(int i=fir[p];i;i=l[i])if(to[i]!=F[0][p])F[0][to[i]]=p,DFS(to[i]),fv[to[i]]=v[i];
11 }
12 int lca(int a,int b){
13     if(dep[a]<dep[b])swap(a,b);
14     int sub=dep[a]-dep[b];
15     for(int i=18;~i;--i)if(sub&1<<i)a=F[i][a];
16     if(a==b)return a;
17     for(int i=18;~i;--i)if(F[i][a]!=F[i][b])a=F[i][a],b=F[i][b];
18     return F[0][a];
19 }
20 void insert(int al,int&p,int o){
21     if(!p)p=++pc;
22     if(!s[al]){R[o]=p;return;}
23     insert(al+1,c[s[al]-‘a‘][p],o);
24 }
25 void buildAC(){
26     q[1]=1;for(int i=0;i<26;++i)c[i][0]=1;f[0]=1;
27     for(int h=1,t=1;h<=t;++h)for(int i=0;i<26;++i)
28         if(c[i][q[h]])f[q[++t]=c[i][q[h]]]=c[i][f[q[h]]];
29         else c[i][q[h]]=c[i][f[q[h]]];
30 }
31 int Fir[S],Ec,L[S],To[S],dfn[S],dfr[S],tim;
32 void Link(int a,int b){L[++Ec]=Fir[a];Fir[a]=Ec;To[Ec]=b;}
33 void dfs(int p){
34     dfn[p]=++tim;
35     for(int i=Fir[p];i;i=L[i])dfs(To[i]);
36     dfr[p]=tim;
37 }
38 int t[S];
39 void add(int p,int w){for(;p<S;p+=p&-p)t[p]+=w;}
40 int Ask(int p,int a=0){for(;p;p^=p&-p)a+=t[p];return a;}
41 int ask(int p){return Ask(dfr[p])-Ask(dfn[p]-1);}
42 void dfsans(int p,int acp){
43     add(dfn[acp],1);
44     //for(int i=1;i<=tim;++i)cout<<Ask(i)-Ask(i-1)<<‘ ‘;cout<<endl;
45     for(int i=0;i<ap[p].size();++i)ans[ap[p][i]>>1]+=Rt[p][i]*ask(R[ap[p][i]]);
46     for(int i=fir[p];i;i=l[i])if(to[i]!=F[0][p])dfsans(to[i],c[v[i]][acp]);
47     add(dfn[acp],-1);
48 }
49 void ins(int p,int o,int r){ap[p].push_back(o);Rt[p].push_back(r);}
50 unsigned long long hsh[S],pw[S],rh;
51 int spj(int a,int b,int c,int o,int x=0){
52     int len=strlen(s),tp=rh=0,sub=max(dep[a]-dep[c]-len+1,0);
53     for(int i=0;i<len;++i)rh=rh*31+s[i]-‘a‘;
54     for(int i=18;~i;--i)if(sub&1<<i)a=F[i][a];
55     ins(a,o<<1,-1);
56     while(a!=c)++tp,hsh[tp]=fv[a],a=F[0][a];
57     sub=max(dep[b]-dep[c]-len+1,0);
58     for(int i=18;~i;--i)if(sub&1<<i)b=F[i][b];
59     ins(b,o<<1|1,-1);
60     a=b;tp+=dep[b]-dep[c];
61     while(b!=c)hsh[tp]=fv[b],tp--,b=F[0][b];
62     tp+=dep[a]-dep[c];
63     for(int i=1;i<=tp;++i)hsh[i]+=hsh[i-1]*31,pw[i]=pw[i-1]*31;
64     for(int i=len;i<=tp;++i)x+=rh==hsh[i]-hsh[i-len]*pw[len];
65     return x;
66 }
67 int main(){//freopen("1.in","r",stdin);
68     cin>>n>>m;pw[0]=1;
69     for(int i=1,a,b;i<n;++i)scanf("%d%d%s",&a,&b,s),link(a,b,s[0]-‘a‘),link(b,a,s[0]-‘a‘);
70     DFS(1);
71     for(int i=1,x,y,c;i<=m;++i){
72         scanf("%d%d%s",&x,&y,s);c=lca(x,y);
73         ins(x,i<<1,1);ins(y,i<<1|1,1);ans[i]=spj(x,y,c,i);
74         insert(0,rt,i<<1|1);
75         reverse(s,s+strlen(s));
76         insert(0,rt,i<<1);
77     }buildAC();
78     for(int i=1;i<=pc;++i)Link(f[i],i);
79     dfs(0);    dfsans(1,rt);
80     for(int i=1;i<=m;++i)printf("%d\n",ans[i]);
81 }

自勉:在家集训10天别再颓了。

2020/01/29 23:50

原文地址:https://www.cnblogs.com/hzoi-DeepinC/p/12241876.html

时间: 2024-10-12 07:25:36

[考试反思]0122省选模拟12:延迟的相关文章

[考试反思]0113省选模拟6:过载

真累啊...离上次放假也挺久,离下次放假也挺久,离上次放出去玩也挺久,离下次放出去玩还不知道有多久... 好累啊...大脑基本成天在挂机了.什么也不想干了... 持续状态不佳.但是今天运气好,所以考试排名看起来还可以. T1没认真读题也没看数据范围,以为是送分题,17分钟写完交了...然后我就把分送出去了 像个弱智一样...但是现在的精神状态的确不太能支持好好做题 幸亏T2是个比较简单的SAM+dp,思维量不大,脑子宕机的时候也能写一写. (归功于当时给大家讲课时稍微有一点理解,要是其它的板子我

[考试反思]0114省选模拟7:迷离

这次考得相对不错,但是没什么水准. 只不过记得T1这道原题而已.虽说我忘了怎么做,而且数据范围不一样...差不多是从头想的. 但是并没有AC,像个弱智一样,有两个细节写的完全不对还有80分运气也是真好. 其实挂了不止两个细节...以为是原题于是上来就写20分钟写完,然后过一会出一个锅... 然后看T2,感觉$O(nk^2)$也许差不多?常数很大...但也不会别的.挺好想但是不是很好写. 于是乎强烈谴责cbx没素质暴力水题考后还不改正解的无脸行径 于是就开始写,写了一个半小时. 看T3,绝对大神题

[考试反思]0117省选模拟10:争夺

T3出了一点锅,于是按IOI赛制打的. 可能也是这辈子唯一一次好好打的IOI赛制了. 提答,又沉里面了,进去就出不来.莫名的虚荣让我根本没有回头看传统题. 于是的确在T3的80%时间里一直单题rk1,然而其实很慌,剩下两道题又怎样? 运气好,T1特别水,T2数据水,T3用奇技淫巧多拿7分于是并列rk1了. 数组没清空丢了1分... 状态差的不行,一下午一道题都没改出来...咕到第二天也没改出来 于是在第二天考试的时候写完三个暴力之后终于把T2A了... 然后第二天考试就炸了,没什么好说的 T1:

[考试反思]0130省选模拟13:悔恨

0+30+20=50.rk8 关键在于: T1写错个变量名挂了100分 kxkxkxkx(激动的语无伦次) 考试过程?上来看T1,一个比较裸的基环树dp,断开环上一条边之后大概就是一个稍加改动的最大独立集. 思路不难想,细节倒是有一点,考场上调啊调啊过了样例又手模了各种数据都过了两个半小时之后很开心就扔了. 然后看T2/3啥都不会,写了俩随机化就走了. 然而T3随机化+贪心是可以AC的.正确性不知道...没写... 最后还有5分钟回T1,突然发现T1可以不是基环树而是基环树森林??? 啊修锅修锅

[考试反思]0220省选模拟27:怪异

怪异的一场考试.考的有点懵 $T1$正解是模拟,人人都能切,然而也没有多少人敢笃定这就是正解吧,常数和精度上下卡着,看运气的题了. $T2$想到了第二档分其实离正解就不远了但是时间不够没往下想.回$T1$卡常去了. $T3$不给状压分,于是猜到一条结论之后并不敢往下想... 然而最后$T1$也没有卡过,考后也在这破玩意上浪费了不少时间... 而且$T3$数据特别谁水暴力可以过,然而因为我不会决策点单调,所以学了学知识点,并没有用暴力水过... T1:飞行棋 大意:长度为$n$的序列,$m$人.每

[考试反思]0410省选模拟67:迷惑

现在想想,先做$T3$真乃人间迷惑行为. 部分分不多的一场考试,$T1$部分分最多结果没花时间光荣爆零,结果正解真的就是一个暴力+大力分类讨论 $T2$也比较可想,然而看着$75pts$的子任务心中有几分慌张,苟了个暴力跑路了. 结果一个弱智$T3$的$10pts$部分分$O(n^8)$暴写了$2.8k$.从这代码长度看是不是$10pts$您施舍的有点少啊. 其余部分分一点用没有,不知道咋想的. T1:链 大意:维护操作:加边,询问有几个点满足:删掉之后图中剩下的都是若干链.$n,m \le 2

[考试反思]1219省选模拟3: 释怀

有些东西渐渐就远去了...不必挂念. 只有时间才拥有如此力量.我们能做的,唯有释怀. 这次的题格外顺手,大概是我的强项了. 但是考得还是不够好吧...感觉可以更高的 今天迎来了学了OI一年多比较重要的一个成就:(虽说是在考后) AC1000道题!还是挺不容易的. 第1000道题是今天的T3.大部分是自己思考的,题也不是很简单,挺好的. 挺过了联赛,现在想要等到下一次整百,可能就要到3月份了. 我还能在OI多久呢? 回到这场考试. T1的数据范围只有10000,让我想起了ALO那道题50000数据

[考试反思]0110省选模拟5:信仰

又倒一啦 10分真是个熟悉的成绩(虽然没有爆零熟悉) 状态一直低迷,没什么好说的 答题策略的话...就那样吧 一眼看出T1是结论题,没有部分分,不好写. 但T2是伯努利数的差不多是模板题了,于是就奔着它去了. 没有注意$0^0=1$.过不去样例最后交的暴力 没有抽时间认真打T3的暴力,因为至多30分. 因为现在30分和0分对我来说是一样的.我是要靠着省选翻盘,拿大众分的话肯定还是退役,求个稳,4个月白学. 现在的答题策略的确不能像联赛时一样了.现在求稳是赢不了了,在稳住200和争取230里我可能

[考试反思]0201省选模拟15:分界

30+10+30+100=170 rk13 17岁的第一仗出师不利. 和外校联考,所以难度不高?后三道题非常简单基本上都是裸的. 但是我做的这是个啥啊... T2广义后缀自动机板子写挂,如果儿子是nq就把儿子修改成nq... T3想到正解然后算错复杂度结果觉得都可以写个简单的于是就把暴力交了上去. T1猜到了第一个结论不会分块暴力也没想到数位dp... 考试前就感觉今天要炸,结果就真炸了. 又当了一次改题大神.半小时一道,中午没睡觉就直接改完了. 下午在uoj上乱跑找好题做ppt.效率挺低的.