金山西山居初赛第三场 HDU 4551~HDU 4553
第一个题就不说了,注意闰年的2月29。
1 #include <map> 2 #include <set> 3 #include <list> 4 #include <queue> 5 #include <stack> 6 #include <cmath> 7 #include <ctime> 8 #include <vector> 9 #include <bitset> 10 #include <cstdio> 11 #include <string> 12 #include <numeric> 13 #include <cstring> 14 #include <cstdlib> 15 #include <iostream> 16 #include <algorithm> 17 #include <functional> 18 using namespace std; 19 typedef long long ll; 20 typedef unsigned long long ull; 21 22 int dx[4]={-1,1,0,0}; 23 int dy[4]={0,0,-1,1};//up down left right 24 bool inmap(int x,int y,int n,int m){if(x<1||x>n||y<1||y>m)return false;return true;} 25 int hashmap(int x,int y,int m){return (x-1)*m+y;} 26 27 #define eps 1e-8 28 #define inf 0x7ffffff 29 #define debug puts("BUG") 30 #define lson l,m,rt<<1 31 #define rson m+1,r,rt<<1|1 32 #define read freopen("in.txt","r",stdin) 33 #define write freopen("out.txt","w",stdout) 34 #define maxn 1005 35 int d[15]={0,31,28,31,30,31,30,31,31,30,31,30,31}; 36 int cnt[maxn][maxn]; 37 struct str 38 { 39 int m,d; 40 }nd[maxn][maxn]; 41 bool isY(int y) 42 { 43 if(y%400==0)return true; 44 if(y%100==0)return false; 45 return y%4==0; 46 } 47 int gcd(int a,int b) 48 { 49 if(b==0)return a; 50 return gcd(b,a%b); 51 } 52 void init() 53 { 54 memset(cnt,0,sizeof(cnt)); 55 for(int i=1;i<13;++i) 56 { 57 for(int j=1;j<=d[i];++j) 58 { 59 int t=gcd(i,j),t2=i*j/t; 60 ++cnt[t][t2]; 61 nd[t][t2].m=i,nd[t][t2].d=j; 62 } 63 } 64 } 65 int main() 66 { 67 //read; 68 int cas; 69 init(); 70 scanf("%d",&cas); 71 for(int xx=1;xx<=cas;++xx) 72 { 73 int a,b,y; 74 scanf("%d%d%d",&a,&b,&y); 75 if(isY(y)&&a==1&&b==58) 76 printf("Case #%d: %04d/%02d/%02d\n",xx,y,2,29); 77 else 78 { 79 if(cnt[a][b]==0) 80 printf("Case #%d: -1\n",xx); 81 else if(cnt[a][b]>1) 82 printf("Case #%d: 1\n",xx); 83 else printf("Case #%d: %04d/%02d/%02d\n",xx,y,nd[a][b].m,nd[a][b].d); 84 } 85 } 86 return 0; 87 }
第二题,题干啰嗦了一堆,又是ASCII码又是循环次数的,貌似其实就是让求所有前缀出现的次数和mod256。
一种正常方法是求所有后缀和最长后缀的最长公共前缀的和,拿第二个样例举例:
0 abab
1 bab
2 ab
3 b
0跟2的最长公共前缀是2,所以能对最后的答案有2个贡献,0跟自己的最长公共前缀是4,所以对最后答案贡献4,最后答案就是6。
这里求最长公共前缀一般需要RMQ预处理,但求所有后缀跟同一个后缀的最长公共前缀就不用了,利用后缀数组的排名性质,找到原串在后缀中的排名,分别向上和向下扫就OK。
1 #include <map> 2 #include <set> 3 #include <list> 4 #include <queue> 5 #include <stack> 6 #include <cmath> 7 #include <ctime> 8 #include <vector> 9 #include <bitset> 10 #include <cstdio> 11 #include <string> 12 #include <numeric> 13 #include <cstring> 14 #include <cstdlib> 15 #include <iostream> 16 #include <algorithm> 17 #include <functional> 18 using namespace std; 19 typedef long long ll; 20 typedef unsigned long long ull; 21 22 int dx[4]={-1,1,0,0}; 23 int dy[4]={0,0,-1,1};//up down left right 24 bool inmap(int x,int y,int n,int m){if(x<1||x>n||y<1||y>m)return false;return true;} 25 int hashmap(int x,int y,int m){return (x-1)*m+y;} 26 27 #define eps 1e-8 28 #define inf 0x7fffffff 29 #define debug puts("BUG") 30 #define lson l,m,rt<<1 31 #define rson m+1,r,rt<<1|1 32 #define read freopen("in.txt","r",stdin) 33 #define write freopen("out.txt","w",stdout) 34 35 #define maxn 100005 36 int wa[maxn],wb[maxn],wv[maxn],wu[maxn]; 37 int cmp(int *r,int a,int b,int l) 38 {return r[a]==r[b]&&r[a+l]==r[b+l];} 39 void da(int *r,int *sa,int n,int m) //求SA[] 40 { 41 int i,j,p,*x=wa,*y=wb,*t; 42 for(i=0;i<m;i++) wu[i]=0; 43 for(i=0;i<n;i++) wu[x[i]=r[i]]++; 44 for(i=1;i<m;i++) wu[i]+=wu[i-1]; 45 for(i=n-1;i>=0;i--) sa[--wu[x[i]]]=i; 46 for(j=1,p=1;p<n;j*=2,m=p) 47 { 48 for(p=0,i=n-j;i<n;i++) y[p++]=i; 49 for(i=0;i<n;i++) if(sa[i]>=j) y[p++]=sa[i]-j; 50 for(i=0;i<n;i++) wv[i]=x[y[i]]; 51 for(i=0;i<m;i++) wu[i]=0; 52 for(i=0;i<n;i++) wu[wv[i]]++; 53 for(i=1;i<m;i++) wu[i]+=wu[i-1]; 54 for(i=n-1;i>=0;i--) sa[--wu[wv[i]]]=y[i]; 55 for(t=x,x=y,y=t,p=1,x[sa[0]]=0,i=1;i<n;i++) 56 x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++; 57 } 58 return; 59 } 60 int rank[maxn],height[maxn]; 61 void calheight(int *r,int *sa,int n) //求height[] 62 { 63 int i,j,k=0; 64 for(i=1;i<=n;i++) rank[sa[i]]=i; 65 for(i=0;i<n;height[rank[i++]]=k) 66 for(k?k--:0,j=sa[rank[i]-1];r[i+k]==r[j+k];k++); 67 return; 68 } 69 #define mod 256 70 char ss[maxn]; 71 int r[maxn],sa[maxn]; 72 int gao(int len) 73 { 74 int ans=len%mod,mx=inf; 75 for(int i=rank[0];i;--i) 76 { 77 mx=min(mx,height[i]); 78 ans+=mx; 79 while(ans>=mod)ans-=mod; 80 }mx=inf; 81 for(int i=rank[0]+1;i<=len;++i) 82 { 83 mx=min(mx,height[i]); 84 ans+=mx; 85 while(ans>=mod)ans-=mod; 86 } 87 return ans; 88 } 89 int main() 90 { 91 //read; 92 while(~scanf("%s",ss)) 93 { 94 int len=strlen(ss); 95 for(int i=0;i<len;++i) 96 r[i]=ss[i]; 97 r[len]=0; 98 da(r,sa,len+1,128); 99 calheight(r,sa,len); 100 printf("%d\n",gao(len)); 101 } 102 return 0; 103 }
比赛的时候不是用的这个做法,因为没有很快想到……。当时看了一下题,统计的是所有的前缀,想到了KMP……。利用NEXT数组的性质,求NEXT[k]的时候会求出1~K这个串前缀和后缀的最长公共前缀(好绕),所以对于每一个k,如果next[k]!=-1,那么就会跟一个原串的某个前缀重复,对答案的贡献就+1。所以求出给出字符串的next,就能求答案了。
1 #include <map> 2 #include <set> 3 #include <list> 4 #include <queue> 5 #include <stack> 6 #include <cmath> 7 #include <ctime> 8 #include <vector> 9 #include <bitset> 10 #include <cstdio> 11 #include <string> 12 #include <numeric> 13 #include <cstring> 14 #include <cstdlib> 15 #include <iostream> 16 #include <algorithm> 17 #include <functional> 18 using namespace std; 19 typedef long long ll; 20 typedef unsigned long long ull; 21 22 int dx[4]={-1,1,0,0}; 23 int dy[4]={0,0,-1,1};//up down left right 24 bool inmap(int x,int y,int n,int m){if(x<1||x>n||y<1||y>m)return false;return true;} 25 int hashmap(int x,int y,int m){return (x-1)*m+y;} 26 27 #define eps 1e-8 28 #define inf 0x7ffffff 29 #define debug puts("BUG") 30 #define lson l,m,rt<<1 31 #define rson m+1,r,rt<<1|1 32 #define read freopen("in.txt","r",stdin) 33 #define write freopen("out.txt","w",stdout) 34 #define maxn 100005 35 char substr[maxn]; 36 int sublen,next[maxn]; 37 void get_next() 38 { 39 sublen=strlen(substr); 40 next[0] = -1; 41 for(int i=1,j=-1;i<sublen;i++) 42 { 43 while(j>-1&&substr[j+1]!=substr[i])j=next[j] ; 44 if(substr[j+1]==substr[i])j++; 45 next[i]=j; 46 } 47 } 48 int main() 49 { 50 //read; 51 while(~scanf("%s",substr)) 52 { 53 get_next();int ans=sublen; 54 for(int i=0;i<sublen;++i) 55 { 56 int j=i; 57 while(~next[j]) 58 { 59 ++ans; 60 while(ans>=256)ans-=256; 61 j=next[j]; 62 } 63 } 64 printf("%d\n",ans); 65 } 66 return 0; 67 }
此题的数据绝对的水,因为当时提交的时候发现取模的时候没用while,应该是错的,结果返回了AC。而且用的时间也太少了,不知道用求NEXT的做法时间复杂度具体是多少,不过应该不会这么快。数据弱的都怀疑自己的做法的正确性。
第三题,做法一目了然,区间合并的线段树,就是维护的信息比较多,由于有女神的存在,需要建两棵树。注意,更新NS那颗树的时候一定也要更新DS那颗树。还有当时读题的时候有个地方不是很清楚,STUDY操作需要清空一个区间的所有请求,这个请求到底指的什么?比如跟NS约会约到一半,突然想STUDY了,可是NS的请求是在STUDY前开始的,到底需不需要清空。后来想,如果不清空就不能用线段树做了吧,干脆就按正常的区间更新做。最后发现按照区间更新做就行,想太多了。
这个题其实就是POJ 3667 Hotel这道题的升级版。
1 #include <map> 2 #include <set> 3 #include <list> 4 #include <queue> 5 #include <stack> 6 #include <cmath> 7 #include <ctime> 8 #include <vector> 9 #include <bitset> 10 #include <cstdio> 11 #include <string> 12 #include <numeric> 13 #include <cstring> 14 #include <cstdlib> 15 #include <iostream> 16 #include <algorithm> 17 #include <functional> 18 using namespace std; 19 typedef long long ll; 20 typedef unsigned long long ull; 21 22 int dx[4]={-1,1,0,0}; 23 //int dy[4]={0,0,-1,1};//up down left right 24 bool inmap(int x,int y,int n,int m){if(x<1||x>n||y<1||y>m)return false;return true;} 25 int hashmap(int x,int y,int m){return (x-1)*m+y;} 26 27 #define eps 1e-8 28 #define inf 0x7fffffff 29 #define debug puts("BUG") 30 #define lson l,m,rt<<1 31 #define rson m+1,r,rt<<1|1 32 #define read freopen("in.txt","r",stdin) 33 #define write freopen("out.txt","w",stdout) 34 #define maxn 100005 35 int ml[maxn<<2],mr[maxn<<2],mx[maxn<<2]; 36 int ml1[maxn<<2],mr1[maxn<<2],mx1[maxn<<2]; 37 int dd[maxn<<2],dd1[maxn<<2]; 38 void pushup(int rt,int l) 39 { 40 int l2=l>>1,l1=l-l2; 41 ml[rt]=ml[rt<<1]; 42 mr[rt]=mr[rt<<1|1]; 43 if(ml[rt]==l1)ml[rt]+=ml[rt<<1|1]; 44 if(mr[rt]==l2)mr[rt]+=mr[rt<<1]; 45 mx[rt]=max(mx[rt<<1],mx[rt<<1|1]); 46 mx[rt]=max(mx[rt],mr[rt<<1]+ml[rt<<1|1]); 47 } 48 void pushdown(int rt,int l) 49 { 50 if(dd[rt]!=-1) 51 { 52 int l2=l>>1,l1=l-l2; 53 dd[rt<<1]=dd[rt<<1|1]=dd[rt]; 54 mx[rt<<1]=ml[rt<<1]=mr[rt<<1]=dd[rt]*l1, 55 mx[rt<<1|1]=ml[rt<<1|1]=mr[rt<<1|1]=dd[rt]*l2; 56 dd[rt]=-1; 57 } 58 } 59 void pushup1(int rt,int l) 60 { 61 int l2=l>>1,l1=l-l2; 62 ml1[rt]=ml1[rt<<1]; 63 mr1[rt]=mr1[rt<<1|1]; 64 if(ml1[rt]==l1)ml1[rt]+=ml1[rt<<1|1]; 65 if(mr1[rt]==l2)mr1[rt]+=mr1[rt<<1]; 66 mx1[rt]=max(mx1[rt<<1],mx1[rt<<1|1]); 67 mx1[rt]=max(mx1[rt],mr1[rt<<1]+ml1[rt<<1|1]); 68 } 69 void pushdown1(int rt,int l) 70 { 71 if(dd1[rt]!=-1) 72 { 73 int l2=l>>1,l1=l-l2; 74 dd1[rt<<1]=dd1[rt<<1|1]=dd1[rt]; 75 mx1[rt<<1]=ml1[rt<<1]=mr1[rt<<1]=dd1[rt]*l1, 76 mx1[rt<<1|1]=ml1[rt<<1|1]=mr1[rt<<1|1]=dd1[rt]*l2; 77 dd1[rt]=-1; 78 } 79 } 80 void build(int l,int r,int rt) 81 { 82 dd[rt]=dd1[rt]=-1; 83 if(l==r) 84 { 85 ml[rt]=mr[rt]=mx[rt]=1; 86 ml1[rt]=mr1[rt]=mx1[rt]=1; 87 return ; 88 } 89 int m=(l+r)>>1; 90 build(lson),build(rson); 91 pushup(rt,r-l+1); 92 pushup1(rt,r-l+1); 93 } 94 void update(int l1,int r1,int v,int l,int r,int rt) 95 { 96 if(l1<=l&&r1>=r) 97 { 98 mx[rt]=ml[rt]=mr[rt]=v*(r-l+1); 99 dd[rt]=v; 100 return ; 101 } 102 pushdown(rt,r-l+1); 103 int m=(l+r)>>1; 104 if(l1<=m)update(l1,r1,v,lson); 105 if(r1>m)update(l1,r1,v,rson); 106 pushup(rt,r-l+1); 107 } 108 void update1(int l1,int r1,int v,int l,int r,int rt) 109 { 110 if(l1<=l&&r1>=r) 111 { 112 mx1[rt]=ml1[rt]=mr1[rt]=v*(r-l+1); 113 dd1[rt]=v; 114 return ; 115 } 116 pushdown1(rt,r-l+1); 117 int m=(l+r)>>1; 118 if(l1<=m)update1(l1,r1,v,lson); 119 if(r1>m)update1(l1,r1,v,rson); 120 pushup1(rt,r-l+1); 121 } 122 int query(int p,int l,int r,int rt) 123 { 124 if(l==r)return l; 125 pushdown(rt,r-l+1); 126 int m=(l+r)>>1,ans; 127 if(mx[rt<<1]>=p)ans=query(p,lson); 128 else if(mr[rt<<1]+ml[rt<<1|1]>=p)ans=m-mr[rt<<1]+1; 129 else ans=query(p,rson); 130 return ans; 131 } 132 int query1(int p,int l,int r,int rt) 133 { 134 if(l==r)return l; 135 pushdown1(rt,r-l+1); 136 int m=(l+r)>>1,ans; 137 if(mx1[rt<<1]>=p)ans=query1(p,lson); 138 else if(mr1[rt<<1]+ml1[rt<<1|1]>=p)ans=m-mr1[rt<<1]+1; 139 else ans=query1(p,rson); 140 return ans; 141 } 142 char ss[maxn]; 143 int main() 144 { 145 //read; 146 int n,m,cas; 147 scanf("%d",&cas); 148 for(int xx=1;xx<=cas;++xx) 149 { 150 printf("Case %d:\n",xx); 151 scanf("%d%d",&n,&m); 152 build(1,n,1); 153 int b,c; 154 while(m--) 155 { 156 scanf("%s",ss); 157 if(ss[0]=='D') 158 { 159 scanf("%d",&b); 160 if(mx[1]<b)puts("fly with yourself"); 161 else 162 { 163 int p=query(b,1,n,1); 164 printf("%d,let's fly\n",p); 165 update(p,p+b-1,0,1,n,1); 166 } 167 } 168 else if(ss[0]=='N') 169 { 170 scanf("%d",&b); 171 if(mx[1]>=b) 172 { 173 int p=query(b,1,n,1); 174 printf("%d,don't put my gezi\n",p); 175 update(p,p+b-1,0,1,n,1); 176 update1(p,p+b-1,0,1,n,1); 177 } 178 else 179 { 180 if(mx1[1]<b)puts("wait for me"); 181 else 182 { 183 int p=query1(b,1,n,1); 184 printf("%d,don't put my gezi\n",p); 185 update(p,p+b-1,0,1,n,1); 186 update1(p,p+b-1,0,1,n,1); 187 } 188 } 189 } 190 else 191 { 192 scanf("%d%d",&b,&c); 193 update(b,c,1,1,n,1); 194 update1(b,c,1,1,n,1); 195 puts("I am the hope of chinese chengxuyuan!!"); 196 } 197 } 198 } 199 return 0; 200 }