matrix_last_acm_1
password 123
A http://acm.hust.edu.cn/vjudge/contest/view.action?cid=96950#problem/A
题意:n个数初始ai,m次操作,查询某个点的值,或者区间加上一个数,对于加的操作,是区间中的每一个元素下标i的倍数 i 2i 3i 。。。都加上这个数。
解法:先预处理出n个下标的所有因子,加的操作只加区间内的,就是一倍的地方。所以对于加操作就是正常的区间加上一个值,对于查询,就需要把这个下标的因子的值都加上。需要输入挂,树状数组。树状数组处理区间加,单点查,【x,y】+=z 在【x】 +z 在【y+1】 -z,最后单点查询就是查询前n项和。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 //#define debug 2 //#define txtout 3 #include<cstdio> 4 #include<cstdlib> 5 #include<cstring> 6 #include<cmath> 7 #include<cctype> 8 #include<ctime> 9 #include<iostream> 10 #include<algorithm> 11 #include<vector> 12 #include<queue> 13 #include<stack> 14 #include<map> 15 #include<set> 16 #define mt(a,b) memset(a,b,sizeof(a)) 17 using namespace std; 18 typedef long long LL; 19 const double eps=1e-8; 20 const double pi=acos(-1.0); 21 const int inf=0x3f3f3f3f; 22 const int M=3e5+10; 23 int a[M]; 24 int n,m; 25 struct G { 26 int op,x,y,z; 27 LL ans; 28 } g[M]; 29 vector<int> fac[M]; 30 int length[M]; 31 class One_Tree_Array { ///一维树状数组 32 static const int M=3e5+10; ///点的个数 33 typedef LL typev; 34 typev a[M]; 35 int n; 36 public: 37 void init(int tn) { ///传入点数,点下标1 开始 38 n=tn; 39 for(int i=0; i<=n; i++) a[i]=0; 40 } 41 int lowb(int t) { 42 return t&(-t); 43 } 44 void add(int i,typev v) { 45 for(; i<=n; a[i]+=v,i+=lowb(i)); 46 } 47 typev sum(int i) { 48 typev s=0; 49 for(; i>0; s+=a[i],i-=lowb(i)); 50 return s; 51 } 52 } gx; 53 void init() { 54 for(int i=1; i<M; i++) { 55 fac[i].clear(); 56 } 57 for(int i=1; i<M; i++) { 58 for(int j=i; j<M; j+=i) { 59 fac[j].push_back(i); 60 } 61 } 62 for(int i=1; i<M; i++) { 63 length[i]=fac[i].size(); 64 } 65 } 66 void solve() { 67 gx.init(n); 68 for(int i=0; i<m; i++) { 69 if(g[i].op&1) { 70 g[i].ans=a[g[i].x]; 71 for(int j=0; j<length[g[i].x]; j++) { 72 g[i].ans+=gx.sum(fac[g[i].x][j]); 73 } 74 continue; 75 } 76 gx.add(g[i].x,g[i].z); 77 gx.add(g[i].y+1,-g[i].z); 78 } 79 } 80 int getint() { 81 int res=0; 82 char tmp; 83 while(!isdigit(tmp=getchar())); 84 do { 85 res=(res<<3)+(res<<1)+tmp-'0'; 86 } while(isdigit(tmp=getchar())); 87 return res; 88 } 89 int main() { 90 #ifdef txtout 91 freopen("in.txt","r",stdin); 92 freopen("out.txt","w",stdout); 93 #endif 94 init(); 95 n=getint(); 96 for(int i=1; i<=n; i++) { 97 a[i]=getint(); 98 } 99 m=getint(); 100 for(int i=0; i<m; i++) { 101 g[i].op=getint(); 102 g[i].x=getint(); 103 if(g[i].op&1) continue; 104 g[i].y=getint(); 105 g[i].z=getint(); 106 } 107 solve(); 108 for(int i=0; i<m; i++) { 109 if(g[i].op&1) { 110 printf("%lld\n",g[i].ans); 111 } 112 } 113 return 0; 114 }
C http://acm.hust.edu.cn/vjudge/contest/view.action?cid=96950#problem/C
题意:有n颗树,每颗树高度ti,每棵树有一只猴子,每秒往上爬一步,ti步到达顶后,每秒往下走一步,到底又开始往上爬,查询任意时刻所有猴子最高的位置。
解法:正解不知道,暴力的话对每个查询遍历所有的树,算出猴子所在高度去最大值,n*m。但是我只测了最高的两个树就ac了。。。样例太水了?还是正解就是如此?有待讨论。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 //#define debug 2 //#define txtout 3 #include<cstdio> 4 #include<cstdlib> 5 #include<cstring> 6 #include<cmath> 7 #include<cctype> 8 #include<ctime> 9 #include<iostream> 10 #include<algorithm> 11 #include<vector> 12 #include<queue> 13 #include<stack> 14 #include<map> 15 #include<set> 16 #define mt(a,b) memset(a,b,sizeof(a)) 17 using namespace std; 18 typedef long long LL; 19 const double eps=1e-8; 20 const double pi=acos(-1.0); 21 const int inf=0x3f3f3f3f; 22 const int M=1e6+10; 23 int a[M]; 24 int b[M]; 25 int n,m; 26 int get_value(int h,int t) { 27 t%=(2*h); 28 if(t<=h) return t; 29 t-=h; 30 return h-t; 31 } 32 void solve() { 33 sort(a,a+n); 34 n=unique(a,a+n)-a; 35 int from=max(0,n-2); 36 for(int i=0; i<m; i++) { 37 if(b[i]<=a[n-1]) continue; 38 int ans=0; 39 for(int j=from; j<n; j++) { 40 ans=max(ans,get_value(a[j],b[i])); 41 } 42 b[i]=ans; 43 } 44 } 45 int getint() { 46 int res=0; 47 char tmp; 48 while(!isdigit(tmp=getchar())); 49 do { 50 res=(res<<3)+(res<<1)+tmp-'0'; 51 } while(isdigit(tmp=getchar())); 52 return res; 53 } 54 int main() { 55 #ifdef txtout 56 freopen("in.txt","r",stdin); 57 freopen("out.txt","w",stdout); 58 #endif 59 n=getint(); 60 for(int i=0; i<n; i++) { 61 a[i]=getint(); 62 } 63 m=getint(); 64 for(int i=0; i<m; i++) { 65 b[i]=getint(); 66 } 67 solve(); 68 for(int i=0; i<m; i++) { 69 printf("%d\n",b[i]); 70 } 71 return 0; 72 }
D http://acm.hust.edu.cn/vjudge/contest/view.action?cid=96950#problem/D
题意:构造一个长度为n的整数数组,使得数组中数的种类至少k种,且任意一个子串的和的种类最少。
解法:用k-1种数,其他全为0,然后前k-1种数一正一负且绝对值相等,例如1 -1 2 -1 3 -3...这样可以使得子串种类尽量少。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 //#define debug 2 //#define txtout 3 #include<cstdio> 4 #include<cstdlib> 5 #include<cstring> 6 #include<cmath> 7 #include<cctype> 8 #include<ctime> 9 #include<iostream> 10 #include<algorithm> 11 #include<vector> 12 #include<queue> 13 #include<stack> 14 #include<map> 15 #include<set> 16 #define mt(a,b) memset(a,b,sizeof(a)) 17 using namespace std; 18 typedef long long LL; 19 const double eps=1e-8; 20 const double pi=acos(-1.0); 21 const int inf=0x3f3f3f3f; 22 const int M=1e3+10; 23 int n,k; 24 int a[M]; 25 void solve(){ 26 int now=1; 27 int la=0; 28 for(int i=0;i<n;i++){ 29 a[i]=0; 30 } 31 for(int i=0;i<k-1;i+=2){ 32 a[la++]=now; 33 if(i+1>=k-1) break; 34 a[la++]=-now; 35 now++; 36 } 37 } 38 int main(){ 39 #ifdef txtout 40 freopen("in.txt","r",stdin); 41 freopen("out.txt","w",stdout); 42 #endif 43 while(~scanf("%d%d",&n,&k)){ 44 solve(); 45 for(int i=0;i<n;i++){ 46 printf("%d%c",a[i],i==n-1?'\n':' '); 47 } 48 } 49 return 0; 50 }
E http://acm.hust.edu.cn/vjudge/contest/view.action?cid=96950#problem/E
题意:给abc三个数,之间有两个符号,+-*,问可得到最小值。
解法:枚举3*3=9种情况。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 //#define debug 2 //#define txtout 3 #include<cstdio> 4 #include<cstdlib> 5 #include<cstring> 6 #include<cmath> 7 #include<cctype> 8 #include<ctime> 9 #include<iostream> 10 #include<algorithm> 11 #include<vector> 12 #include<queue> 13 #include<stack> 14 #include<map> 15 #include<set> 16 #define mt(a,b) memset(a,b,sizeof(a)) 17 using namespace std; 18 typedef long long LL; 19 const double eps=1e-8; 20 const double pi=acos(-1.0); 21 const int inf=0x3f3f3f3f; 22 const int M=1e5+10; 23 int a,b,c; 24 int solve(){ 25 int res=inf; 26 res=min(res,a+b+c); 27 res=min(res,a+b-c); 28 res=min(res,a+b*c); 29 res=min(res,a-b+c); 30 res=min(res,a-b-c); 31 res=min(res,a-b*c); 32 res=min(res,a*b+c); 33 res=min(res,a*b-c); 34 res=min(res,a*b*c); 35 return res; 36 } 37 int main(){ 38 #ifdef txtout 39 freopen("in.txt","r",stdin); 40 freopen("out.txt","w",stdout); 41 #endif 42 while(~scanf("%d%d%d",&a,&b,&c)){ 43 printf("%d\n",solve()); 44 } 45 return 0; 46 }
F http://acm.hust.edu.cn/vjudge/contest/view.action?cid=96950#problem/F
题意:定义p(u,v)为u,v两点距离,定义p(u,v,w)= p( v, u) + p( v, w) + p( u, w),求多少对uv满足v ≠ u 并且p( v, u) ≥ p( v, u, w) 对于所有的 w。
解法:根据要求可以发现,必须是所有点都共线,且最两端的点,才能满足恰好相等,可以由三角形两边和大于第三边证明。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 //#define debug 2 //#define txtout 3 #include<cstdio> 4 #include<cstdlib> 5 #include<cstring> 6 #include<cmath> 7 #include<cctype> 8 #include<ctime> 9 #include<iostream> 10 #include<algorithm> 11 #include<vector> 12 #include<queue> 13 #include<stack> 14 #include<map> 15 #include<set> 16 #define mt(a,b) memset(a,b,sizeof(a)) 17 using namespace std; 18 typedef long long LL; 19 const double eps=1e-8; 20 const double pi=acos(-1.0); 21 const int inf=0x3f3f3f3f; 22 const int M=2e5+10; 23 struct point{ 24 LL x,y; 25 int pid; 26 friend bool operator <(const point &a,const point &b){ 27 return a.x<b.x||(a.x==b.x&&a.y<b.y); 28 } 29 }p[M]; 30 int n; 31 LL xmult(point p1,point p2,point p0){ ///计算向量叉积(P1-P0)x(P2-P0) 32 return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y); 33 } 34 bool not_on_line(){ 35 for(int i=2;i<n;i++){ 36 if(xmult(p[0],p[1],p[i])) return true; 37 } 38 return false; 39 } 40 int main(){ 41 #ifdef txtout 42 freopen("in.txt","r",stdin); 43 freopen("out.txt","w",stdout); 44 #endif 45 while(~scanf("%d",&n)){ 46 for(int i=0;i<n;i++){ 47 scanf("%lld%lld",&p[i].x,&p[i].y); 48 p[i].pid=i+1; 49 } 50 if(not_on_line()){ 51 puts("0"); 52 continue; 53 } 54 puts("1"); 55 sort(p,p+n); 56 printf("%d %d\n",p[0].pid,p[n-1].pid); 57 } 58 return 0; 59 }
G http://acm.hust.edu.cn/vjudge/contest/view.action?cid=96950#problem/G
题意:给n堆石头,每堆都是奇数个,D和S轮流玩,D先玩,每次玩家可以选一堆石头,将其分为3堆且每堆都是奇数,最后谁没法分就输。
解法:发现一堆 a 个石头能被分 a/2 向下取整次。统计一下能分的次数的奇偶就知道胜负。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 //#define debug 2 //#define txtout 3 #include<cstdio> 4 #include<cstdlib> 5 #include<cstring> 6 #include<cmath> 7 #include<cctype> 8 #include<ctime> 9 #include<iostream> 10 #include<algorithm> 11 #include<vector> 12 #include<queue> 13 #include<stack> 14 #include<map> 15 #include<set> 16 #define mt(a,b) memset(a,b,sizeof(a)) 17 using namespace std; 18 typedef long long LL; 19 const double eps=1e-8; 20 const double pi=acos(-1.0); 21 const int inf=0x3f3f3f3f; 22 const int M=1e3+10; 23 int a[M]; 24 int n; 25 char str[][32]={"Daenerys","Stannis"}; 26 int solve(){ 27 int res=0; 28 for(int i=0;i<n;i++){ 29 res+=a[i]/2; 30 } 31 return res&1^1; 32 } 33 int main(){ 34 #ifdef txtout 35 freopen("in.txt","r",stdin); 36 freopen("out.txt","w",stdout); 37 #endif 38 while(~scanf("%d",&n)){ 39 for(int i=0;i<n;i++){ 40 scanf("%d",&a[i]); 41 } 42 puts(str[solve()]); 43 } 44 return 0; 45 }
H http://acm.hust.edu.cn/vjudge/contest/view.action?cid=96950#problem/H
题意:输入n条竖线m条横线,每条横线有权值,从左上角走到右下角,花费定义为路径上最小权值,求最大花费。
解法:答案只会从四种情况中产生,一是第一条竖线和最后一条横线,二是第一条横线和最后一条竖线,三是第一条和最后一条竖线加权值最大的横线,四是反之亦然。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 //#define debug 2 //#define txtout 3 #include<cstdio> 4 #include<cstdlib> 5 #include<cstring> 6 #include<cmath> 7 #include<cctype> 8 #include<ctime> 9 #include<iostream> 10 #include<algorithm> 11 #include<vector> 12 #include<queue> 13 #include<stack> 14 #include<map> 15 #include<set> 16 #define mt(a,b) memset(a,b,sizeof(a)) 17 using namespace std; 18 typedef long long LL; 19 const double eps=1e-8; 20 const double pi=acos(-1.0); 21 const int inf=0x3f3f3f3f; 22 const int M=1e5+10; 23 int a[M]; 24 int b[M]; 25 int n,m; 26 int get(int len,int s[]){ 27 int res=0; 28 for(int i=1;i<len;i++){ 29 if(s[res]<s[i]){ 30 res=i; 31 } 32 } 33 return s[res]; 34 } 35 int get_min(int a,int b,int c){ 36 return min(a,min(b,c)); 37 } 38 int solve(){ 39 int res=0; 40 int max_a=get(n,a); 41 int max_b=get(m,b); 42 res=max(res,min(a[0],b[m-1])); 43 res=max(res,min(a[n-1],b[0])); 44 res=max(res,get_min(a[0],a[n-1],max_b)); 45 res=max(res,get_min(b[0],b[m-1],max_a)); 46 return res; 47 } 48 int main(){ 49 #ifdef txtout 50 freopen("in.txt","r",stdin); 51 freopen("out.txt","w",stdout); 52 #endif 53 while(~scanf("%d%d",&n,&m)){ 54 for(int i=0;i<n;i++){ 55 scanf("%d",&a[i]); 56 } 57 for(int i=0;i<m;i++){ 58 scanf("%d",&b[i]); 59 } 60 printf("%d\n",solve()); 61 } 62 return 0; 63 }
I http://acm.hust.edu.cn/vjudge/contest/view.action?cid=96950#problem/I
题意:A觉得素数是好的,B觉得因子个数是素数的数是好的。求L到R之间有多少个AB同时觉得好或者同时觉得不好的。
解法:打表发现,不是平方数的一定满足,平方数有的满足,有的不满足,所以只要处理出那些平方数不合法,对一个区间,答案就是R-L+1区间内数的个数,减去在这个区间内的不合法的平方数的个数。关键如何处理出不合法的平方数。R最大10的12次方,所以平方数共有10的6次方个数。枚举每一个数,分解质因数,该数的平方就是每种质因子个数*2.根据一个公式,因子的个数等于每种因子个数 设为ai 因子个数等于 (a1+1)*。。。*(an+1);所有因子个数加1累乘。算出来后,首先平方数肯定不是素数,所以A不喜欢,那么不合法的就是b要喜欢,就是因子的个数要是素数。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 //#define debug 2 //#define txtout 3 #include<cstdio> 4 #include<cstdlib> 5 #include<cstring> 6 #include<cmath> 7 #include<cctype> 8 #include<ctime> 9 #include<iostream> 10 #include<algorithm> 11 #include<vector> 12 #include<queue> 13 #include<stack> 14 #include<map> 15 #include<set> 16 #define mt(a,b) memset(a,b,sizeof(a)) 17 using namespace std; 18 typedef long long LL; 19 const double eps=1e-8; 20 const double pi=acos(-1.0); 21 const int inf=0x3f3f3f3f; 22 const int M=1e6+10; 23 class Sieve_primes { ///筛素数 24 static const int M=1e6+10; ///数值范围 25 public: 26 int prime[M],mark[M],len; ///mark[i]存i 的最小因子 27 public: 28 Sieve_primes() { 29 len=0; 30 mt(mark,0); 31 mark[0]=mark[1]=1; 32 for(int i=2; i<M; i++) { 33 if(!mark[i]) prime[len++]=mark[i]=i; 34 for(int j=0; prime[j]*i<M; j++) { 35 mark[i*prime[j]]=prime[j]; 36 if(!(i%prime[j])) break; 37 } 38 } 39 } 40 int getlen() { ///返回<M 素数的个数 41 return len; 42 } 43 int getprime(int id) { ///返回第id(<len)个素数 44 return prime[id]; 45 } 46 bool isprime(int x) { ///素数时mark[i]==i 47 return mark[x]==x; 48 } 49 }gx; 50 LL L,R; 51 vector<LL> a; 52 int fac[128]; 53 int find_fac_before_sieve(int n) { //筛完素数后用,n<M 54 int cnt=0; 55 while(gx.mark[n]!=1) { 56 fac[cnt++]=gx.mark[n]; 57 n/=gx.mark[n]; 58 } 59 return cnt; 60 } 61 void init() { 62 a.clear(); 63 for(int i=2;i<M;i++){ 64 int cnt=find_fac_before_sieve(i); 65 int sum=1; 66 for(int j=0;j<cnt;j++){ 67 int last=j; 68 for(int k=j;k<cnt;k++){ 69 if(fac[j]!=fac[k]) break; 70 last=k; 71 } 72 sum*=((last-j+1)*2+1); 73 j=last; 74 } 75 if(gx.isprime(sum)){ 76 a.push_back(1LL*i*i); 77 } 78 } 79 } 80 LL solve() { 81 LL tmp=upper_bound(a.begin(),a.end(),R)-lower_bound(a.begin(),a.end(),L); 82 return R-L+1-tmp; 83 } 84 int main() { 85 #ifdef txtout 86 freopen("in.txt","r",stdin); 87 freopen("out.txt","w",stdout); 88 #endif 89 init(); 90 while(~scanf("%lld%lld",&L,&R)) { 91 printf("%lld\n",solve()); 92 } 93 return 0; 94 }
J http://acm.hust.edu.cn/vjudge/contest/view.action?cid=96950#problem/J
题意:输入n个ABP串,可能是ABP的非空子序列,每次可以加一段连续的A or B or P,对于某一个串,必须按照ABP的顺序添加。问如何排列使得加的次数最小。
解法:先把串分类,同类放一起,一共7个情况,然后7的全排列验证这个排列需要加几次,取最小值。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 //#define debug 2 //#define txtout 3 #include<cstdio> 4 #include<cstdlib> 5 #include<cstring> 6 #include<cmath> 7 #include<cctype> 8 #include<ctime> 9 #include<iostream> 10 #include<algorithm> 11 #include<vector> 12 #include<queue> 13 #include<stack> 14 #include<map> 15 #include<set> 16 #define mt(a,b) memset(a,b,sizeof(a)) 17 using namespace std; 18 typedef long long LL; 19 const double eps=1e-8; 20 const double pi=acos(-1.0); 21 const int inf=0x3f3f3f3f; 22 const int M=1e5+10; 23 char abp[]="ABP"; 24 char all_abp[8][8]; 25 vector<int> id[8]; 26 struct S{ 27 string str; 28 int pid; 29 friend bool operator <(const S &a,const S &b){ 30 return a.str<b.str; 31 } 32 }now; 33 vector<S> v; 34 string str[8]; 35 int n; 36 int answer[M]; 37 char input[M][8]; 38 int ans_id[8]; 39 void init(){ 40 for(int i=1;i<8;i++){ 41 int len=0; 42 for(int j=0;j<3;j++){ 43 if((i>>j)&1){ 44 all_abp[i-1][len++]=abp[j]; 45 } 46 } 47 all_abp[i-1][len]=0; 48 } 49 } 50 void init_id(){ 51 for(int i=0;i<8;i++){ 52 id[i].clear(); 53 } 54 for(int i=0;i<n;i++){ 55 for(int j=0;j<7;j++){ 56 if(!strcmp(all_abp[j],input[i])){ 57 id[j].push_back(i+1); 58 break; 59 } 60 } 61 } 62 } 63 bool have(string s,char c){ 64 int ls=s.size(); 65 for(int i=0;i<ls;i++){ 66 if(s[i]==c) return true; 67 } 68 return false; 69 } 70 int get_cost(){ 71 int lv=v.size(); 72 for(int i=0;i<lv;i++){ 73 str[i]=v[i].str; 74 } 75 int res=0; 76 for(int i=0;i<3;i++){ 77 for(int j=0;j<lv;j++){ 78 if(!have(str[j],abp[i])) continue; 79 int last=j; 80 for(int k=j;k<lv;k++){ 81 if(have(str[k],abp[i])){ 82 last=k; 83 } 84 else{ 85 break; 86 } 87 } 88 res++; 89 j=last; 90 } 91 } 92 return res; 93 } 94 int solve(){ 95 init_id(); 96 v.clear(); 97 for(int i=0;i<7;i++){ 98 if(id[i].size()==0) continue; 99 now.str=(string)all_abp[i]; 100 now.pid=i; 101 v.push_back(now); 102 } 103 sort(v.begin(),v.end()); 104 int res=inf; 105 int lv=v.size(); 106 do{ 107 int tmp=get_cost(); 108 if(res>tmp){ 109 res=tmp; 110 for(int i=0;i<lv;i++){ 111 ans_id[i]=v[i].pid; 112 } 113 } 114 }while(next_permutation(v.begin(),v.end())); 115 int la=0; 116 for(int i=0;i<lv;i++){ 117 int len=id[ans_id[i]].size(); 118 for(int j=0;j<len;j++){ 119 answer[la++]=id[ans_id[i]][j]; 120 } 121 } 122 return res; 123 } 124 int main(){ 125 #ifdef txtout 126 freopen("in.txt","r",stdin); 127 freopen("out.txt","w",stdout); 128 #endif 129 init(); 130 while(~scanf("%d",&n)){ 131 for(int i=0;i<n;i++){ 132 scanf("%s",input[i]); 133 } 134 printf("%d\n",solve()); 135 for(int i=0;i<n;i++){ 136 printf("%d%c",answer[i],i==n-1?'\n':' '); 137 } 138 } 139 return 0; 140 }
K http://acm.hust.edu.cn/vjudge/contest/view.action?cid=96950#problem/K
题意:有n朵花,每个花的价值是一个整数,一开始站在1号,要一次给每一朵花浇水,每朵花只浇水一次,花费1,在花之间走动,花费是两朵花的距离,浇花的顺序必须保证花的价值是不递减序列。
解法:首先按照花的价值分类,先走价值低的,比如一堆2,一堆3,必须把2的全走完,再走3.对于同一种价值的花,只可能先到左端点,再到右端点,或者先右后左。因此可以定义dp【i】【j】表示处理完前 i 种价值的花停留在 j 端点,0左端点,1右端点。4个方向都可以转移。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 //#define debug 2 //#define txtout 3 #include<cstdio> 4 #include<cstdlib> 5 #include<cstring> 6 #include<cmath> 7 #include<cctype> 8 #include<ctime> 9 #include<iostream> 10 #include<algorithm> 11 #include<vector> 12 #include<queue> 13 #include<stack> 14 #include<map> 15 #include<set> 16 #define mt(a,b) memset(a,b,sizeof(a)) 17 using namespace std; 18 typedef long long LL; 19 const double eps=1e-8; 20 const double pi=acos(-1.0); 21 const LL inf=0x3f3f3f3f3f3f3f3fLL; 22 const int M=1e5+10; 23 int a[M]; 24 int b[M]; 25 int l[M]; 26 int r[M]; 27 int n; 28 map<int,int> mp; 29 LL dp[M][2]; 30 int init_l_r(){ 31 for(int i=0;i<n;i++){ 32 b[i]=a[i]; 33 } 34 sort(b,b+n); 35 int Index=0; 36 for(int i=0;i<n;i++){ 37 if(!mp.count(b[i])){ 38 mp[b[i]]=Index++; 39 } 40 } 41 int len=mp.size(); 42 for(int i=0;i<len;i++){ 43 l[i]=-1; 44 } 45 for(int i=0;i<n;i++){ 46 int to=mp[a[i]]; 47 if(l[to]==-1){ 48 l[to]=i; 49 } 50 r[to]=i; 51 } 52 return len; 53 } 54 void init_dp(int len){ 55 for(int i=0;i<len;i++){ 56 for(int j=0;j<2;j++){ 57 dp[i][j]=inf; 58 } 59 } 60 } 61 int get_l_r(int i,int j){ 62 if(!j) return l[i]; return r[i]; 63 } 64 LL getcost(int i,int j,int k){ 65 int s1=get_l_r(i,j); 66 int s2=get_l_r(i+1,k^1); 67 int s3=get_l_r(i+1,k); 68 return abs(s1-s2)+abs(s2-s3); 69 } 70 LL solve(){ 71 int len=init_l_r(); 72 init_dp(len); 73 dp[0][1]=r[0]; 74 for(int i=0;i+1<len;i++){ 75 for(int j=0;j<2;j++){ 76 for(int k=0;k<2;k++){ 77 dp[i+1][k]=min(dp[i+1][k],dp[i][j]+getcost(i,j,k)); 78 } 79 } 80 } 81 return n+min(dp[len-1][0],dp[len-1][1]); 82 } 83 int main(){ 84 #ifdef txtout 85 freopen("in.txt","r",stdin); 86 freopen("out.txt","w",stdout); 87 #endif 88 while(~scanf("%d",&n)){ 89 for(int i=0;i<n;i++){ 90 scanf("%d",&a[i]); 91 } 92 printf("%lld\n",solve()); 93 } 94 return 0; 95 }
L http://acm.hust.edu.cn/vjudge/contest/view.action?cid=96950#problem/L
题意:输入n场比赛名字,时间,题数,提交数,每次提交的题号,结果,最后比赛名字时间原样输出,没提交的题输出. 提交通过输出o 未通过X。
解法:模拟题,怎么说怎么做。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 //#define debug 2 //#define txtout 3 #include<cstdio> 4 #include<cstdlib> 5 #include<cstring> 6 #include<cmath> 7 #include<cctype> 8 #include<ctime> 9 #include<iostream> 10 #include<algorithm> 11 #include<vector> 12 #include<queue> 13 #include<stack> 14 #include<map> 15 #include<set> 16 #define mt(a,b) memset(a,b,sizeof(a)) 17 using namespace std; 18 typedef long long LL; 19 const double eps=1e-8; 20 const double pi=acos(-1.0); 21 const int inf=0x3f3f3f3f; 22 const int M=1e2+10; 23 struct G{ 24 char name[M],date[16]; 25 int type[16],number; 26 void init(){ 27 for(int i=0;i<13;i++){ 28 type[i]=0; 29 } 30 } 31 void add(char a,char b){ 32 int to=a-'A'; 33 if(b=='A'){ 34 type[to]=2; 35 return ; 36 } 37 if(type[to]==0){ 38 type[to]=1; 39 } 40 } 41 }g[M]; 42 int n,m; 43 char buffer[M]; 44 char str[]=".xo"; 45 char divide[]="+------------------------------+--------+-------------+"; 46 char titles[]="|Contest name |Date |ABCDEFGHIJKLM|"; 47 void get_line(char s[]){ 48 int ls=0; 49 while(true){ 50 char c=getchar(); 51 if(c=='\n') break; 52 s[ls++]=c; 53 } 54 s[ls]=0; 55 } 56 void output_string(char s[]){ 57 for(int i=0;s[i];i++){ 58 putchar(s[i]); 59 } 60 } 61 void output_space(int x){ 62 for(int i=0;i<x;i++){ 63 putchar(' '); 64 } 65 } 66 void output_type(int x){ 67 for(int i=0;i<g[x].number;i++){ 68 putchar(str[g[x].type[i]]); 69 } 70 } 71 void output(int id){ 72 putchar('|'); 73 output_string(g[id].name); 74 output_space(30-strlen(g[id].name)); 75 putchar('|'); 76 output_string(g[id].date); 77 putchar('|'); 78 output_type(id); 79 output_space(13-g[id].number); 80 puts("|"); 81 puts(divide); 82 } 83 int main(){ 84 #ifdef txtout 85 freopen("in.txt","r",stdin); 86 freopen("out.txt","w",stdout); 87 #endif 88 while(~scanf("%d",&n)){ 89 getchar(); 90 for(int i=0;i<n;i++){ 91 get_line(g[i].name); 92 get_line(g[i].date); 93 scanf("%d%d",&g[i].number,&m); 94 getchar(); 95 g[i].init(); 96 while(m--){ 97 get_line(buffer); 98 g[i].add(buffer[0],buffer[2]); 99 } 100 } 101 puts(divide); 102 puts(titles); 103 puts(divide); 104 for(int i=0;i<n;i++){ 105 output(i); 106 } 107 } 108 return 0; 109 }
end