金山西山居初赛第三场 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 }
View Code

第二题,题干啰嗦了一堆,又是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 }
View Code

比赛的时候不是用的这个做法,因为没有很快想到……。当时看了一下题,统计的是所有的前缀,想到了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 }
View Code

此题的数据绝对的水,因为当时提交的时候发现取模的时候没用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 }
View Code
原文地址:https://www.cnblogs.com/mcflurry/p/3086640.html