4.1:T1原题,T2码农板子题,T3板子题
4.2
好像是三个出题人分别出的
以及#define *** 傻逼
T1
思维好题
转成树形DP,$dp[i][j]$表示点i值为j的方案数,记录前缀和转移
1 #include<cstdio> 2 #include<cctype> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 const int N=28,Maxn=100000,mod=12015858; 7 int n,rt,cnt,p[N],noww[N],goal[N],deg[N]; 8 int dp[N][Maxn+5],dwt[N],upt[N],var[N]; char s1[N],s2[N]; 9 int Getnum(char *s) 10 { 11 int ret=0; 12 for(int i=0,l=strlen(s);i<l;i++) 13 ret=(ret<<1)+(ret<<3)+(s[i]^48); 14 return ret; 15 } 16 void Link(int f,int t){noww[++cnt]=p[f],p[f]=cnt,goal[cnt]=t,deg[t]++;} 17 void Add(int &x,int y){x=(x+y>=mod)?(x+y-mod):(x+y);} 18 void Mul(int &x,int y){x=1ll*x*y%mod;} 19 void DFS(int nde) 20 { 21 for(int i=p[nde];i;i=noww[i]) DFS(goal[i]); 22 for(int i=dwt[nde];i<=upt[nde];i++) 23 { 24 dp[nde][i]=1; 25 for(int j=p[nde],g;j;j=noww[j]) 26 (var[g=goal[j]]==nde)?Mul(dp[nde][i],dp[g][Maxn]-dp[g][i-1]+mod):Mul(dp[nde][i],dp[g][i]); 27 } 28 for(int i=1;i<=Maxn;i++) Add(dp[nde][i],dp[nde][i-1]); 29 } 30 int main() 31 { 32 scanf("%d",&n); 33 for(int i=1;i<=n;i++) 34 { 35 scanf("%s%s",s1,s2); 36 if(!isdigit(s1[0])) 37 { 38 int x=Getnum(s2),ch=s1[0]-'a'+1; 39 dwt[i]=1,upt[i]=x,Link(ch,i),var[i]=ch; 40 } 41 else if(!isdigit(s2[0])) 42 { 43 int x=Getnum(s1),ch=s2[0]-'a'+1; 44 dwt[i]=x,upt[i]=Maxn,Link(ch,i); 45 } 46 else 47 dwt[i]=Getnum(s1),upt[i]=Getnum(s2); 48 } 49 int ans=1; 50 for(int i=1;i<=n;i++) 51 if(!deg[i]) DFS(i),Mul(ans,dp[i][Maxn]); 52 printf("%d\n",ans); 53 return 0; 54 }
T2
单调栈干掉包含的情况,然后决策单调性
***造数据的写着1<=L,R<=1e6然后就开始造负数,于是快读挂了
代码是考场写的有点丑
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #define Temp template<class T> 5 using namespace std; 6 const int N=1000005; 7 8 char BF[1<<23],*P1=BF,*P2=BF; 9 char Gc(){return (P1==P2&&(P2=(P1=BF)+fread(BF,1,1<<21,stdin),P1==P2)?EOF:*P1++);} 10 void Fread(int &x) 11 { 12 x=0; char ch=Gc(); 13 while(!isdigit(ch)) ch=Gc(); 14 while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=Gc(); 15 } 16 17 struct a 18 { 19 int l,r; 20 }arr[N],tmp[N]; 21 bool operator < (a x,a y) 22 { 23 return x.l==y.l?x.r<y.r:x.l<y.l; 24 } 25 void Msort(int l,int r) 26 { 27 if(l>=r) return; 28 int mid=(l+r)>>1; 29 Msort(l,mid),Msort(mid+1,r); 30 int p=l,q=mid+1,pq=l; 31 while(p<=mid&&q<=r) 32 tmp[pq++]=(arr[q]<arr[p])?arr[q++]:arr[p++]; 33 while(p<=mid) tmp[pq++]=arr[p++]; 34 while(q<=r) tmp[pq++]=arr[q++]; 35 for(int i=l;i<=r;i++) arr[i]=tmp[i]; 36 } 37 38 int n,cnt,top,stk[N],ll[N],rr[N]; long long ans[N],anss; 39 inline void Maxi(long long &a,long long b){if(a<b) a=b;} 40 inline void Ins(int x){stk[++top]=x;} 41 inline long long Bina(int x) 42 { 43 int l=1,r=top,ret=top; 44 while(l<=r) 45 { 46 int mid=(l+r)>>1; 47 if(rr[stk[mid]]>=x) 48 l=mid+1,ret=mid; 49 else 50 r=mid-1; 51 } 52 return rr[stk[ret]]-ll[stk[ret]]; 53 } 54 long long Calc(int an,int cn) 55 { 56 an=stk[an],cn=stk[cn]; 57 return 1ll*(rr[cn]-ll[an])*(rr[an]-ll[cn]); 58 } 59 void Solve(int lp,int rp,int l,int r) 60 { 61 if(l>r) return; 62 if(lp==rp) 63 for(int i=l;i<=r;i++) 64 ans[i]=Calc(lp,i); 65 else 66 { 67 int mid=(l+r)>>1; long long t; 68 int pt=lp,bo=lp,od=min(rp,mid-1); 69 for(int i=bo;i<=od;i++) 70 if((t=Calc(i,mid))>ans[mid]) ans[mid]=t,pt=i; 71 if(l!=r) Solve(lp,pt,l,mid),Solve(pt,rp,mid+1,r); 72 } 73 } 74 int main() 75 { 76 Fread(n); 77 register int i; int j,k; 78 for(i=1;i<=n;i++) 79 Fread(j),Fread(k),arr[i]=(a){j,k}; 80 Msort(1,n); 81 for(i=1;i<=n;i++) 82 ll[i]=arr[i].l,rr[i]=arr[i].r; 83 stk[top=1]=1; 84 for(i=2;i<=n;i++) 85 rr[i]<=rr[stk[top]]?Maxi(anss,1ll*(rr[i]-ll[i])*Bina(rr[i])):Ins(i); 86 Solve(1,top-1,2,top); long long asn=0; 87 for(i=1;i<=top;i++) Maxi(asn,ans[i]); 88 printf("%lld",max(asn,anss)); 89 return 0; 90 }
T3
出题人对自己认识还是很清楚的,果然是***人出***题
为什么这么说,可以看看下面的***出题人的题解:
(*直球辱骂*)
4.4
T1
自然数幂和能插出来,不提
把前缀和的a+id拆成a和id两部分,分别再插
总复杂度$O(k^2)$
T2
奇怪DP
把一个数分成三段,前面是一坨数,中间是一坨极长的连续9,最后是一个数
然后$dp[i][j][k]$表示前面一坨里最大的是i,中间j个9,最后是k
***DP(错乱
T3
先压成正常的Trie,建fail树,把询问挂在点上,树上差分,树状数组维护
(抽象