暑假集训test-8-31(am)

1.字符串匹配

看到题目以为真是字符串题结果是数学题。。70分做法很傻逼然而我更傻逼只有30。。。

正解是发现两个位置会匹配当且仅当mod gcd(lena,lenb)同余,在一个lcm(lena,lenb)的长度内所有模gcd同余的位置会一一匹配。我大概只能感性理解一下和随便证一下模gcd同余则可以匹配。

然后用乘法原理计数。代码超短的。

 1 //Achen
 2 #include<algorithm>
 3 #include<iostream>
 4 #include<cstring>
 5 #include<cstdlib>
 6 #include<vector>
 7 #include<cstdio>
 8 #include<queue>
 9 #include<cmath>
10 #include<set>
11 #include<map>
12 #define Formylove return 0
13 #define For(i,a,b) for(int i=(a);i<=(b);i++)
14 #define Rep(i,a,b) for(int i=(a);i>=(b);i--)
15 const int N=2e6+7;
16 typedef long long LL;
17 typedef double db;
18 using namespace std;
19 int n,m,cnt[30],lena,lenb;
20 LL ans;
21 char a[N],b[N];
22 
23 template<typename T>void read(T &x)  {
24     char ch=getchar(); x=0; T f=1;
25     while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
26     if(ch=='-') f=-1,ch=getchar();
27     for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
28 }
29 
30 LL gcd(LL a,LL b) { return !b?a:gcd(b,a%b); }
31 
32 #define ANS
33 int main() {
34 #ifdef ANS
35     freopen("string.in","r",stdin);
36     freopen("string.out","w",stdout);
37 #endif
38     read(n); read(m);
39     scanf("%s",a); lena=strlen(a);
40     scanf("%s",b); lenb=strlen(b);
41     LL d=gcd(lena,lenb);
42     For(t,0,d-1) {
43         memset(cnt,0,sizeof(cnt));
44         For(i,0,lena/d-1) 
45             cnt[a[i*d+t]-'a']++;
46         For(i,0,lenb/d-1) 
47             ans+=cnt[b[i*d+t]-'a']; 
48     }
49     ans*=n*d/lenb;
50     printf("%lld\n",ans);
51     Formylove;
52 }
View Code

 

2.积木大赛

感觉这题很傻逼啊。少有的不是模板但是可以秒切的题。

枚举最高点的位置,二分最高点,再往左右二分满足最高点条件(从最高点开始依次减1)的最近位置,这个可以用st表或者线段树什么的维护。算算要达到最高点积木够不够即可。

 1 //Achen
 2 #include<algorithm>
 3 #include<iostream>
 4 #include<cstring>
 5 #include<cstdlib>
 6 #include<vector>
 7 #include<cstdio>
 8 #include<queue>
 9 #include<cmath>
10 #include<set>
11 #include<map>
12 #define Formylove return 0
13 #define For(i,a,b) for(int i=(a);i<=(b);i++)
14 #define Rep(i,a,b) for(int i=(a);i>=(b);i--)
15 const int N=100005; 
16 typedef long long LL;
17 typedef double db;
18 using namespace std;
19 int n,m;
20 LL h[N],st1[N][17],st2[N][17],sum[N],ans;
21 
22 template<typename T>void read(T &x)  {
23     char ch=getchar(); x=0; T f=1;
24     while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
25     if(ch=='-') f=-1,ch=getchar();
26     for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
27 }
28 
29 void make_st() {
30     For(i,1,n) st1[i][0]=h[i]+i,st2[i][0]=h[i]+(n-i+1);
31     For(j,1,16) For(i,1,n) {
32         if(i+(1<<j)-1<=n) 
33             st1[i][j]=max(st1[i][j-1],st1[i+(1<<j-1)][j-1]);
34         if(i-(1<<j)+1>=1) 
35             st2[i][j]=max(st2[i][j-1],st2[i-(1<<j-1)][j-1]);
36     }
37 }
38 
39 int ck(int pos,LL x) {
40     int l=pos,r=pos;
41     Rep(i,16,0) if(r+(1<<i)-1<=n&&st1[r][i]<x+pos)
42         r+=(1<<i);
43     Rep(i,16,0) if(l-(1<<i)+1>=1&&st2[l][i]<x+(n-pos+1))
44         l-=(1<<i);
45     LL nd=0;
46     if(l<1||r>n) return 0;
47     if(l+1<=pos) { 
48         l++; 
49         nd=nd+(x+x-(pos-l))*(pos-l+1)/2-(sum[pos]-sum[l-1]); 
50     }
51     if(r-1>=pos) { 
52         r--; 
53         nd=nd+(x+x-(r-pos))*(r-pos+1)/2-(sum[r]-sum[pos-1]); 
54     }
55     return nd-(x-h[pos])<=m;
56 }
57 
58 LL solve(int pos) {
59     LL l=h[pos],r=h[pos]+m,rs=l;
60     while(l<=r) {
61         int mid=((l+r)>>1);
62         if(ck(pos,mid)) rs=mid,l=mid+1;
63         else r=mid-1;
64     }
65     return rs;
66 }
67 
68 #define ANS
69 int main() {
70 #ifdef ANS
71     freopen("block.in","r",stdin);
72     freopen("block.out","w",stdout);
73 #endif
74     read(n); read(m);
75     For(i,1,n) read(h[i]),sum[i]=sum[i-1]+h[i];
76     make_st();
77     For(i,1,n) 
78         ans=max(ans,solve(i));
79     printf("%lld\n",ans);
80     Formylove;
81 }
View Code

 

3.考古研究

30分和70分还是比较好做,但是傻逼地搞了好久t1然后这天考得就很爆炸。

一张我的草稿:

就是草稿,所以非常乱。

继续70分是思路,倒着考虑最后地表的每个点经过若干次沉降后到达的位置。

对于这个转过的网格图,从左到右x从1~n,从上到下y从1~n,每个格子上的权值就是它的x坐标减y坐标除以2

操作逆过来,一种是选x较大的一部分区间x+=2*L,一种是选y较小的部分区间y-=2*L

每次操作线段树上二分在操作范围内的区间,区间修改即可。直接二分好写很多就没写线段树上二分了。

 

 

 1 //Achen
 2 #include<algorithm>
 3 #include<iostream>
 4 #include<cstring>
 5 #include<cstdlib>
 6 #include<vector>
 7 #include<cstdio>
 8 #include<queue>
 9 #include<cmath>
10 #include<set>
11 #include<map>
12 #define Formylove return 0
13 #define For(i,a,b) for(int i=(a);i<=(b);i++)
14 #define Rep(i,a,b) for(int i=(a);i>=(b);i--)
15 const int N=200007;
16 typedef long long LL;
17 typedef double db;
18 using namespace std;
19 int n,m;
20 
21 template<typename T>void read(T &x)  {
22     char ch=getchar(); x=0; T f=1;
23     while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
24     if(ch=='-') f=-1,ch=getchar();
25     for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
26 }
27 
28 struct node {
29     int x,d,l;
30 }q[N];
31 
32 #define lc x<<1
33 #define rc (x<<1|1)
34 #define mid ((l+r)>>1)
35 struct sgtree {
36     LL lz[N<<2];
37     void down(int x) {
38         if(!lz[x]) return ;
39         lz[lc]+=lz[x]; lz[rc]+=lz[x];
40         lz[x]=0;
41     }
42     
43     void update(int x,int l,int r,int ql,int qr,int v) {
44         if(l>=ql&&r<=qr) {
45             lz[x]+=v; return ; 
46         }
47         down(x);
48         if(ql<=mid) update(lc,l,mid,ql,qr,v);
49         if(qr>mid) update(rc,mid+1,r,ql,qr,v);
50     }
51     
52     LL qry(int x,int l,int r,int pos) {
53         if(l==r) return lz[x];
54         down(x);
55         if(pos<=mid) return qry(lc,l,mid,pos);
56         else return qry(rc,mid+1,r,pos);
57     }
58 }sgx,sgy;
59 
60 #define ANS
61 int main() {
62 #ifdef ANS
63     freopen("geologic.in","r",stdin);
64     freopen("geologic.out","w",stdout);
65 #endif
66     read(n); read(m);
67     For(i,1,m) {
68         read(q[i].x);
69         read(q[i].d);
70         read(q[i].l);
71     }
72     For(i,1,n) sgx.update(1,1,n,i,i,i),sgy.update(1,1,n,i,i,i);
73     Rep(i,m,1) {
74         if(q[i].d==1) { //down 
75             int l=1,r=n,rs=-1;
76             while(l<=r) {
77                 if(sgx.qry(1,1,n,mid)<=q[i].x) rs=mid,l=mid+1;
78                 else r=mid-1;
79             }
80             if(rs!=-1) sgy.update(1,1,n,1,rs,-2*q[i].l); 
81         }
82         else { //right
83             int l=1,r=n,rs=-1;
84             while(l<=r) {
85                 if(sgy.qry(1,1,n,mid)>q[i].x) rs=mid,r=mid-1;
86                 else l=mid+1;
87             }
88             if(rs!=-1) sgx.update(1,1,n,rs,n,2*q[i].l);
89         }    
90     }
91     For(i,1,n) printf("%lld\n",(sgx.qry(1,1,n,i)-sgy.qry(1,1,n,i))/2);
92     Formylove;
93 }
View Code

 

 

posted @ 2018-09-01 22:19  啊宸  阅读(138)  评论(0编辑  收藏  举报