正睿 2018 提高组十连测 Day6

时间:2021-04-11 09:49:49

前言:lzz出题,海星,没有想象中的那样毒瘤

T1:

emmmmmmm大佬们做法都很简单,用树状数组维护加稍微推一下50几行就出来了。我用线段树nlogn维护每个数前面小于它大于它的个数和后面小于它大于它的个数,开始写了个(n^2+)暴力,后面照着暴力推出正解式子,最终233行才A...还是思路不行,下面看正解想法:考虑分别统计(a,b)的合法数p,(c,d) 的合法数q ,则ans=p*q减去一些不合法的四元组(a,b,c,d)的数⽬。这⾥不合法的四元组只有四种情况:a==c,a==d,b==c,b==d 。以a==c为例,把

每个数(i,si)看成点 ,则只需要对每个点求其右上方点数乘以其右下方点数即可,即往后比a小的*往后比a大的,离散化一下树状数组维护就能解决,同样对剩余三种情况处理并从答案减去即可。

本质入手,深入思考

上代码:

  1 #include<bits/stdc++.h>
  2 #define maxn 100005
  3 using namespace std;
  4 int n;
  5 typedef long long ll;
  6 struct node{
  7     int v,id;//离散 
  8 
  9     friend bool operator <(node a,node b){
 10         if(a.v!=b.v) return a.v<b.v;
 11         else return a.id<b.id;
 12     }
 13 }nd[maxn];
 14 bool cmp(node a,node b){
 15     return a.id<b.id;
 16 }
 17 int rk[maxn],lc[maxn<<1],rc[maxn<<1],rt=0,np=0;
 18 ll sumq[maxn<<1],sumh[maxn<<1],addq[maxn<<1],addh[maxn<<1];
 19 void build(int &now,int l,int r){
 20     now=++np;
 21     if(l==r){
 22        sumq[now]=l-1;sumh[now]=n-l;return;    
 23     }
 24     
 25     int m=l+r>>1;
 26     build(lc[now],l,m);
 27     build(rc[now],m+1,r);
 28 }
 29 void downloadq(int now){
 30     if(addq[now]!=0){
 31         sumq[lc[now]]+=addq[now];
 32         addq[lc[now]]+=addq[now];
 33         sumq[rc[now]]+=addq[now];
 34         addq[rc[now]]+=addq[now];
 35         addq[now]=0;
 36     }
 37 } 
 38 void updateq(int now,int l,int r,int i,int j,int v){
 39     if(l>=i&&r<=j){
 40         sumq[now]+=v;
 41         addq[now]+=v;
 42         return;
 43     }
 44     downloadq(now);
 45     
 46     int m=l+r>>1;
 47     if(j<=m) updateq(lc[now],l,m,i,j,v);
 48     else if(i>m) updateq(rc[now],m+1,r,i,j,v);
 49     else{
 50         updateq(lc[now],l,m,i,j,v);
 51         updateq(rc[now],m+1,r,i,j,v);
 52     } 
 53 }
 54 void downloadh(int now){
 55     if(addh[now]!=0){
 56         sumh[lc[now]]+=addh[now];
 57         addh[lc[now]]+=addh[now];
 58         sumh[rc[now]]+=addh[now];
 59         addh[rc[now]]+=addh[now];
 60         addh[now]=0;
 61     }
 62 } 
 63 void updateh(int now,int l,int r,int i,int j,int v){
 64     if(l>=i&&r<=j){
 65         sumh[now]+=v;
 66         addh[now]+=v;
 67         return;
 68     }
 69     downloadh(now);
 70     
 71     int m=l+r>>1;
 72     if(j<=m) updateh(lc[now],l,m,i,j,v);
 73     else if(i>m) updateh(rc[now],m+1,r,i,j,v);
 74     else{
 75         updateh(lc[now],l,m,i,j,v);
 76         updateh(rc[now],m+1,r,i,j,v);
 77     } 
 78 }
 79 ll cdq(int now,int l,int r,int x){
 80     if(l==r) return sumq[now];
 81     
 82     downloadq(now);
 83     
 84     int m=l+r>>1;
 85     if(x<=m) return cdq(lc[now],l,m,x);
 86     else return cdq(rc[now],m+1,r,x);
 87 }
 88 ll cdh(int now,int l,int r,int x){
 89     if(l==r) return sumh[now];
 90     
 91     downloadh(now);
 92     
 93     int m=l+r>>1;
 94     if(x<=m) return cdh(lc[now],l,m,x);
 95     else return cdh(rc[now],m+1,r,x);
 96 }
 97 ll st[maxn],top;
 98 ll rsumq[maxn],rsumh[maxn],summq=0,summh=0,xsumq[maxn],xsumh[maxn];//提取出来 
 99 void calc(){
100     /*ll ans=0;
101     for(int i=1;i<=n;i++){
102         for(int j=i+1;j<=n;j++){
103             if(nd[j].v>nd[i].v){
104                 ans+=(summq-rsumq[i]-rsumq[j]);
105             }
106         }
107     }
108     printf("%lld",ans);*/
109     /*ll ans=0;
110     for(int i=1;i<=n;i++){
111         for(int j=1;j<=n;j++){
112             if(i==j) continue;
113             ll lx=rsumq[i],sx=rsumh[j];
114             if(j<i&&nd[j].v>nd[i].v) lx--;
115             else if(j<i&&nd[j].v<nd[i].v) sx--;//只有这种... 
116             int calc=0;
117             if(j<i){
118                 for(int k=j+1;k<i;k++)
119                 if(nd[k].v>nd[i].v&&nd[k].v>nd[j].v){calc++;}
120             }
121             if(lx<0) lx=0; 
122             if(sx<0) sx=0;
123             ans+=lx*sx;
124             ans-=calc;
125         }
126     } 
127     printf("%lld",ans);*/
128     ll ans=0;
129     ans+=1ll*summq*summh;
130     for(int i=1;i<=n;i++){
131         ans-=1ll*rsumq[i]*rsumh[i];
132         ans-=1ll*xsumq[i]*xsumh[i];
133         ans-=1ll*rsumq[i]*xsumq[i];
134         ans-=1ll*xsumh[i]*rsumh[i];
135     } 
136     printf("%lld",ans);
137 }
138 bool cmp2(node a,node b){
139     if(a.v!=b.v) return a.v>b.v;
140     else return a.id<b.id;
141 }
142 void run(){
143     sort(nd+1,nd+n+1,cmp2);
144     for(int i=1;i<=n;i++){
145         rk[i]=nd[i].id;
146     }
147     sort(nd+1,nd+n+1,cmp);
148     rt=np=0;
149     memset(sumq,0,sizeof(sumq));
150     memset(sumh,0,sizeof(sumh));
151     memset(addh,0,sizeof(addh));
152     memset(addq,0,sizeof(addq));
153     build(rt,1,n);
154     
155     for(int i=1;i<=n;i++){
156        int t=rk[i];//rk存的是id 
157        top=0;
158        st[++top]=t;
159        int id=rk[i+1];
160        while(nd[id].v==nd[t].v&&i+1<=n){
161           st[++top]=id;i++;
162           id=rk[i+1];           
163        }
164        /*int pos=1; 
165        while(pos<=top){
166              /*int h=n-st[pos];
167              h-=top-pos;
168              int tt=st[pos]; 
169              updateh(rt,1,n,1,tt-1,-1);
170              updateq(rt,1,n,tt+1,n,-1);
171              pos++;
172        }*/
173        for(int j=1;j<=top;j++){
174           int tt=st[j]; 
175              if(1<=tt-1) updateh(rt,1,n,1,tt-1,-1);
176              if(tt+1<=n) updateq(rt,1,n,tt+1,n,-1);
177              //printf("%lld %lld\n",cdq(rt,1,n,54),cdh(rt,1,n,54));
178        }
179        for(int j=1;j<=top;j++){
180               int tt=st[j]; 
181            xsumq[tt]=cdq(rt,1,n,tt);
182            xsumh[tt]=cdh(rt,1,n,tt);
183        }
184     } 
185 }
186 void init(){
187     scanf("%d",&n);
188     for(int i=1;i<=n;i++) scanf("%d",&nd[i].v),nd[i].id=i;
189     sort(nd+1,nd+n+1);
190     for(int i=1;i<=n;i++){
191         rk[i]=nd[i].id;
192     }
193     sort(nd+1,nd+n+1,cmp);
194     build(rt,1,n);
195     for(int i=1;i<=n;i++){
196        int t=rk[i];//rk存的是id 
197        top=0;
198        st[++top]=t;
199        int id=rk[i+1];
200        while(nd[id].v==nd[t].v){
201           st[++top]=id;i++;
202           id=rk[i+1];           
203        }
204        /*int pos=1; 
205        while(pos<=top){
206              /*int h=n-st[pos];
207              h-=top-pos;
208              int tt=st[pos]; 
209              updateh(rt,1,n,1,tt-1,-1);
210              updateq(rt,1,n,tt+1,n,-1);
211              pos++;
212        }*/
213        for(int j=1;j<=top;j++){
214           int tt=st[j]; 
215              if(1<=tt-1) updateh(rt,1,n,1,tt-1,-1);
216              if(tt+1<=n) updateq(rt,1,n,tt+1,n,-1);
217        }
218        for(int j=1;j<=top;j++){
219               int tt=st[j]; 
220            rsumq[tt]=cdq(rt,1,n,tt);
221            summq+=rsumq[tt];
222            rsumh[tt]=cdh(rt,1,n,tt);
223            summh+=rsumh[tt];
224        }
225     } 
226     run();
227     calc();
228 }
229 int main(){
230     init();
231     
232     return 0;
233 }

T2:

  一道动规题.....耐人琢磨,整体是从大字典序往小字典序传承,从右边状态推到左边状态,f[l][r][pos][c]思维表示字符串从s[l]到s[r]第pos位至少为c。关于方法数的计算可以理解一下,下有部分代码注释....

上代码:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define maxn 55
 4 typedef long long ll;
 5 const ll mod=990804011;
 6 ll f[maxn][maxn][25][30];
 7 int n,len=0;
 8 char s[maxn][25];
 9 ll dp(int l,int r,int pos,int c){
10     if(f[l][r][pos][c]!=-1) return  f[l][r][pos][c];
11     ll &t=f[l][r][pos][c];//代名
12     if(c==27) return t=0;//已超
13     if(pos>len) return t=(l==r?1:0);//说明已经匹配完了,如果两个是一个字符串还行,严格小于
14     t=dp(l,r,pos,c+1);//c+1可以,那c可以,累加
15     for(int mid=l;mid<=r;mid++){
16         if(s[mid][pos]=='?'&&c==0) break;
17         if(s[mid][pos]!='?'&&c!=s[mid][pos]-'a'+1) break;//任一个不满足都无法转移,只能继承上一个
18         ll tt=dp(l,mid,pos+1,0);
19         if(mid<r) tt=tt*dp(mid+1,r,pos,c+1)%mod;
20         t=(t+tt)%mod;
21     }   
22     return t;
23 }
24 void init(){
25     scanf("%d",&n);
26     for(int i=1;i<=n;i++){
27         scanf("%s",s[i]+1);
28         int lenn=strlen(s[i]+1);
29         len=max(len,lenn);
30     }
31     for(int i=1;i<=n;i++){
32         for(int j=int(strlen(s[i]+1)+1);j<=len;j++){
33             s[i][j]='a'-1;//补位设为0
34         }
35     }
36     memset(f,-1,sizeof(f));
37     printf("%lld",dp(1,n,1,0));
38 }
39 int main(){
40     init();
41 
42     return 0;
43 }

T3:

先咕咕咕了,回去有时间补....