【20161108】总结
啊啊啊,今天的题目比较简单。
然后我我我。。因为吸取以前教训,花时间拍了2题,然后就A了那两题,
其他两题,一个没搞边界爆了数组,一个打完点分治没调过样例,直接交暴力了。。ORZ
1、
1.Game
【题目描述】
明明和亮亮在玩一个游戏。桌面上一行有n个格子,一些格子中放着棋子。明明和亮亮轮流选择如下方式中的一种移动棋子(图示中o表示棋子,*表示空着的格子):
1) 当一枚棋子的右边是空格子的话,可以将这枚棋子像右移动一格。
**o*** -> ***o**
2) 当一枚棋子的右边连续两个都有棋子,并且这个棋子往右边数第3格没有棋子,那么可以将这个棋子可以跳过去那两个棋子
**ooo* -> ***oo*
当任何一枚棋子到达最右边的格子时,这枚棋子自动消失。当一方不能移动时,这方输。假设明明和亮亮都采取最优策略,明明先走,谁将取胜?
【输入数据】
第一行一个整数T表示数据组数, 0 < T < 10。
之后T组数据,每组两行,第一行n 表示格子个数,第二行n个字符表示每个格子的情况,o表示有棋子,*表示空着。
【输出数据】
对于每组数据一个输出,M表示明明赢,L表示亮亮赢。
【样例输入】
4
2
*o
5
*o***
6
**o**o
14
*o***ooo**oo**
【样例输出】
L
M
M
L
【数据范围】
0 <T < 10
对于50%的数据, n < 20。
对于100%的数据, n < 1000。
刚看题,似曾相识。。
仔细一看,有点不一样。。。
再看,,像是阶梯nim,开心地打了起来。
然后。。。错了。。。。看了一看。。好像又不怎么一样。。
怎么破好心慌= =
打完2、3题后回来做。。。先打个暴力。。。敲敲敲....
感觉可以先弄到最右边,因为根据奇偶可以确定谁先遇到后面一排棋子的状态。
然后谁赢呢,这样可以找规律了耶,然后找规律:MMLLMMLLMMLL....找到了ORZ
试试对不对,一排,哇!!!成功了!!!【我自己其实是蒙B的。。。
然后就A了。。。
放题解:
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<iostream> 5 #include<algorithm> 6 using namespace std; 7 #define Maxn 1010 8 9 char s[Maxn]; 10 11 int main() 12 { 13 int T; 14 scanf("%d",&T); 15 while(T--) 16 { 17 int n; 18 scanf("%d",&n); 19 scanf("%s",s); 20 int sum=0,p=0,q=0,ans=0; 21 for(int i=n-2;i>=0;i--) 22 { 23 if(s[i]=='o') p+=sum,q++; 24 else sum++; 25 } 26 if(p%2==0) 27 { 28 if(q%4==1||q%4==2) printf("M\n"); 29 else printf("L\n"); 30 } 31 else 32 { 33 if(q%4==1||q%4==2) printf("L\n"); 34 else printf("M\n"); 35 36 } 37 // else printf("M\n"); 38 } 39 return 0; 40 }
2、
2.Walk
【题目描述】
有一块n *n 的土地上,明明和亮亮站在(1,1)处。每块地上写有一个数字a(i, j)。现在他们决定玩一个游戏,每一秒钟,他们俩走向相邻且坐标变大的格子(从(x,y)到(x+1,y)或者从(x,y)到(x,y+1)),他们俩可以按照不同方式来走,最后经过2n-1步到达(n,n)处。明明和亮亮每一秒钟计算他们站的两个位置上数字的差的绝对值,他们希望这些差值的和最大,请问这个最大的和是多少?
【输入数据】
第一行一个正整数n。
后面n行,每行n个整数,分别表示每块地上的数字。
【输出数据】
一个整数,表示最大的差值的和。
【样例输入】
4
1 2 3 4
1 5 3 2
8 1 3 4
3 2 1 5
【样例输出】
13
【数据范围】
n <= 100, 每块地上的数字的绝对值不超过300。
这题R了ORZ。。。
有小伙伴数组没有开够。。。
打的时候十分有信心,我这样打数组不用开两倍的,不会爆!!
然后就。。没有判边界ORZ。。。
bac代码:
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<iostream> 5 #include<algorithm> 6 using namespace std; 7 #define Maxn 110 8 9 int a[Maxn][Maxn],f[Maxn][Maxn][Maxn]; 10 11 int mymax(int x,int y) {return x>y?x:y;} 12 int myabs(int x) {return x>0?x:-x;} 13 14 int main() 15 { 16 int n; 17 scanf("%d",&n); 18 for(int i=1;i<=n;i++) 19 for(int j=1;j<=n;j++) 20 scanf("%d",&a[i][j]); 21 memset(f,0,sizeof(f)); 22 for(int i=2;i<=2*n-1;i++) 23 for(int j=1;j<i;j++) if(i-j<=n) 24 for(int k=1;k<i;k++) if(i-k<=n) 25 { 26 if(j>n||k>n) continue; 27 int y1=i-j,y2=i-k; 28 if(j<=n&&k<=n) f[j+1][y1][k+1]=mymax(f[j+1][y1][k+1],f[j][y1][k]+myabs(a[j+1][y1]-a[k+1][y2])); 29 if(j<=n&&y2<=n) f[j+1][y1][k]=mymax(f[j+1][y1][k],f[j][y1][k]+myabs(a[j+1][y1]-a[k][y2+1])); 30 if(y1<=n&&k<=n) f[j][y1+1][k+1]=mymax(f[j][y1+1][k+1],f[j][y1][k]+myabs(a[j][y1+1]-a[k+1][y2])); 31 if(y1<=n&&y2<=n) f[j][y1+1][k]=mymax(f[j][y1+1][k],f[j][y1][k]+myabs(a[j][y1+1]-a[k][y2+1])); 32 } 33 printf("%d\n",f[n][n][n]); 34 return 0; 35 }
3、
3. Trip
【题目描述】
小朋友们出去郊游,明明和亮亮负责在草地上开一个篝火晚会。这个草地你可以认为是又 N * M 块单位长度为1的小正方形的草组成。
显然有的地方草长的好,有的地方长的不好,坐在上面显然舒服度是不一样的,于是每一块草都有一个舒服度 F。
现在明明和亮亮要选定一个 a*b 的草场作为晚会的地点,小朋友们就坐在上面,显然他希望小朋友们坐的最舒服!
不过别急,篝火晚会怎么能少了篝火呢,篝火需要占用 c*d 的草地,当然,篝火必须严格放置在选定的草地的内部,也就是说,篝火的边界不能和选定操场的边界有公共部分,不然学生们怎么围着篝火开晚会呢?
给定 N*M 大草地每一块的舒服度,寻找一个 a*b 的草地,除去一个严格内部的 c*d 的子草地,使得总的舒服度最大。
【输入数据】
第1行:6个整数,M , N, b, a, d, c
第2~N+1行:每行 M 个整数,第 i行j列的整数 Fi,j 表示,第 i行j列的单位草地的舒服度。
【输出数据】
一个整数,表示最大的舒服值。
【样例输入】
8 5 5 3 2 1
1 5 10 3 7 1 2 5
6 12 4 4 3 3 1 5
2 4 3 1 6 6 19 8
1 1 1 3 4 2 4 5
6 6 3 3 3 2 2 2
【样例输出】
70
【数据说明】
下面的图片就是对样例的解释,阴影区域就是最佳的选择方案。
比如方案 4 1 4 1 就是显然非法的,因为篝火出现出现在了选定草地的边界,学生们无法严格围住篝火。
【数据范围】
1 ≤ Fi,j ≤ 100
3 ≤ a ≤ N
3 ≤ b ≤ M
1 ≤ c ≤ a-2
1 ≤ d ≤ b-2
对于 40% 的数据 N,M ≤ 10
对于 60% 的数据 N,M ≤ 150
对于 100% 的数据 N,M ≤ 1000
各种乱搞的题目,我用倍增各种乱搞,还有前缀和。。。
其实一开始对倍增是拒绝的,上了个厕所之后。。。
还是倍增吧,区间最值,想不到其他更好的【线段树是什么?
然后正解是,单调队列。。。。ORZ。。这是个滑动窗口啊傻!!!
倍增垃圾版:
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<iostream> 5 #include<algorithm> 6 using namespace std; 7 #define Maxn 1010 8 9 int w[Maxn][Maxn],sm[Maxn][Maxn],v[Maxn][Maxn]; 10 int mn[Maxn][Maxn]; 11 int f[Maxn][12]; 12 int n,m,b,a,d,c; 13 14 int mymin(int x,int y) {return x<y?x:y;} 15 int mymax(int x,int y) {return x>y?x:y;}; 16 17 void ffind() 18 { 19 for(int i=c;i<=n;i++) 20 for(int j=d;j<=m;j++) 21 v[i][j]=sm[i][j]-sm[i-c][j]-sm[i][j-d]+sm[i-c][j-d]; 22 /*for(int i=1;i<=n;i++) 23 { 24 for(int j=1;j<=m;j++) 25 printf("%d ",v[i][j]); 26 printf("\n"); 27 }*/ 28 29 30 int id=0; 31 while((1<<id)<=b-d-1) id++;id--; 32 // printf("id=%d\n",id); 33 // printf("xx=%d\n",b-d-1); 34 35 for(int i=c;i<=n;i++) 36 { 37 memset(f,63,sizeof(63)); 38 for(int j=d;j<=m;j++) 39 { 40 f[j][0]=v[i][j]; 41 for(int k=1;j-(1<<k)+1>=d;k++) 42 f[j][k]=mymin(f[j-(1<<k-1)][k-1],f[j][k-1]); 43 if(j>=b-2) mn[i][j]=mymin(f[j][id],f[j-b+d+1+(1<<id)][id]); 44 } 45 } 46 for(int i=1;i<=n;i++) 47 for(int j=1;j<=m;j++) v[i][j]=mn[i][j]; 48 49 /*for(int i=1;i<=n;i++) 50 { 51 for(int j=1;j<=m;j++) 52 printf("%d ",v[i][j]); 53 printf("\n"); 54 } 55 printf("\n");*/ 56 id=0; 57 while((1<<id)<=a-c-1) id++;id--; 58 // printf("id=%d\n",id); 59 // printf("xx=%d\n",a-c-1); 60 memset(mn,63,sizeof(63)); 61 for(int j=b-2;j<=m;j++) 62 { 63 memset(f,63,sizeof(63)); 64 for(int i=c;i<=n;i++) 65 { 66 f[i][0]=v[i][j]; 67 for(int k=1;i-(1<<k)+1>=c;k++) 68 f[i][k]=mymin(f[i-(1<<k-1)][k-1],f[i][k-1]); 69 if(i>=a-2) mn[i][j]=mymin(f[i][id],f[i-a+c+1+(1<<id)][id]); 70 } 71 } 72 /*for(int i=1;i<=n;i++) 73 { 74 for(int j=1;j<=m;j++) 75 printf("%d ",mn[i][j]); 76 printf("\n"); 77 }*/ 78 } 79 80 void init() 81 { 82 scanf("%d%d%d%d%d%d",&m,&n,&b,&a,&d,&c); 83 for(int i=1;i<=n;i++) 84 for(int j=1;j<=m;j++) 85 scanf("%d",&w[i][j]); 86 memset(sm,0,sizeof(sm)); 87 for(int i=1;i<=n;i++) 88 for(int j=1;j<=m;j++) 89 sm[i][j]=sm[i-1][j]+sm[i][j-1]-sm[i-1][j-1]+w[i][j]; 90 /*for(int i=1;i<=n;i++) 91 { 92 for(int j=1;j<=m;j++) 93 printf("%d ",sm[i][j]); 94 printf("\n"); 95 }*/ 96 ffind(); 97 } 98 99 int main() 100 { 101 init(); 102 int ans=0; 103 for(int i=a;i<=n;i++) 104 for(int j=b;j<=m;j++) 105 { 106 ans=mymax(ans,sm[i][j]-sm[i-a][j]-sm[i][j-b]+sm[i-a][j-b]-mn[i-1][j-1]); 107 } 108 printf("%d\n",ans); 109 return 0; 110 }
看看我调试痕迹就知道,我的心酸。。
4、
刚看,天哪怎么没说部分分。。。
先随便打了个n^3暴力,回去拍了1、3题、、、
回来。。。
怎么可能。。。至少要枚举两个端点吧都n^2了。。
然后好像弄前缀然后在两个点上面乱搞。。。
然后。。。三个点有一个点是枚举的lca,就是根。。。
根啊根。。。。像是点分治【点分治可以过诶。。。nlogn^2
11点,还有1个小时。。。。
11:30打完,准备调试。。scy:现在交了。。。ORZ。。。样例还错着。。。
交暴力吧骚年。。。
bac——
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<iostream> 5 #include<algorithm> 6 using namespace std; 7 #define Maxn 100010 8 #define Mod 1000003 9 #define INF 0xfffffff 10 #define LL long long 11 12 LL v[Maxn],ny[Mod+11100],k; 13 int n; 14 15 struct node 16 { 17 int x,y,next; 18 }t[Maxn*2];int len; 19 int first[Maxn]; 20 21 void ins(int x,int y) 22 { 23 t[++len].x=x;t[len].y=y; 24 t[len].next=first[x];first[x]=len; 25 } 26 27 int mymax(int x,int y) {return x>y?x:y;} 28 int mymin(int x,int y) {return x<y?x:y;} 29 30 LL qpow(LL x,LL b) 31 { 32 LL ans=1; 33 while(b) 34 { 35 if(b&1) ans=(ans*x)%Mod; 36 x=(x*x)%Mod; 37 b>>=1; 38 } 39 return ans; 40 } 41 42 bool vis[Maxn]; 43 int sm[Maxn],mx[Maxn]; 44 int ffind(int x,int tot,int f) 45 { 46 sm[x]=1;mx[x]=0; 47 int rt=-1; 48 for(int i=first[x];i;i=t[i].next) if(t[i].y!=f&&vis[t[i].y]) 49 { 50 int y=t[i].y; 51 int rrt=ffind(y,tot,x); 52 if(mx[rrt]<mx[rt]||rt==-1) rt=rrt; 53 mx[x]=mymax(mx[x],sm[y]); 54 sm[x]+=sm[y]; 55 } 56 mx[x]=mymax(mx[x],tot-sm[x]); 57 if(rt==-1||mx[x]<mx[rt]) return x; 58 return rt; 59 } 60 61 LL dis[Maxn]; 62 int q[Maxn],ql,wr[Mod+1100]; 63 int a1,a2; 64 void dfs(int x,int f,int rt) 65 { 66 dis[x]=(v[x]*dis[f])%Mod; 67 q[++ql]=x; 68 LL A=(((ny[dis[x]]*dis[rt])%Mod)*k)%Mod; 69 if(wr[A]<=n) 70 { 71 int n1=mymin(wr[A],x),n2=mymax(wr[A],x); 72 if(n1<a1||(n1==a1&&n2<a2)) a1=n1,a2=n2; 73 } 74 75 for(int i=first[x];i;i=t[i].next) if(t[i].y!=f&&vis[t[i].y]) 76 { 77 int y=t[i].y; 78 dfs(y,x,rt); 79 } 80 } 81 82 83 void get_ans(int x) 84 { 85 ql=0;dis[x]=v[x];wr[v[x]]=x; 86 int now; 87 vis[x]=0; 88 for(int i=first[x];i;i=t[i].next) if(vis[t[i].y]) 89 { 90 now=ql; 91 dfs(t[i].y,x,x); 92 for(int j=now+1;j<=ql;j++) wr[dis[q[j]]]=mymin(wr[dis[q[j]]],q[j]); 93 } 94 95 for(int i=1;i<=ql;i++) wr[dis[q[i]]]=INF; 96 wr[v[x]]=INF; 97 for(int i=first[x];i;i=t[i].next) if(vis[t[i].y]) 98 { 99 int rt=ffind(t[i].y,sm[t[i].y],0); 100 // printf(".\n"); 101 // printf("%d\n",t[i].y); 102 get_ans(rt); 103 } 104 } 105 106 int main() 107 { 108 // for(int i=1;i<Mod;i++) ny[i]=qpow(i,Mod-2); 109 ny[1]=1; 110 for(int i=2;i<Mod;i++) ny[i]=(Mod-Mod/i)*ny[Mod%i]%Mod; 111 // printf(".\n"); 112 scanf("%d%lld",&n,&k); 113 for(int i=1;i<=n;i++) scanf("%d",&v[i]); 114 len=0; 115 memset(first,0,sizeof(first)); 116 for(int i=1;i<n;i++) 117 { 118 int x,y; 119 scanf("%d%d",&x,&y); 120 ins(x,y);ins(y,x); 121 } 122 memset(vis,1,sizeof(vis)); 123 int rt=ffind(1,n,0); 124 memset(wr,63,sizeof(wr)); 125 a1=a2=INF; 126 get_ans(rt); 127 if(a1==INF) printf("No solution\n"); 128 else printf("%d %d\n",a1,a2); 129 return 0; 130 }
(我好像还没说怎么做ORZ)
后来看奥爷爷代码。。
他是预处理逆元,然后,我才知道可以这样预处理逆元,那么就是nlogn的了ORZ。。
2016-11-09 16:27:47