matrix_last_acm_1

password 123

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项和。

  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
",g[i].ans);
111         }
112     }
113     return 0;
114 }
View Code

http://acm.hust.edu.cn/vjudge/contest/view.action?cid=96950#problem/C

题意:有n颗树,每颗树高度ti,每棵树有一只猴子,每秒往上爬一步,ti步到达顶后,每秒往下走一步,到底又开始往上爬,查询任意时刻所有猴子最高的位置。

解法:正解不知道,暴力的话对每个查询遍历所有的树,算出猴子所在高度去最大值,n*m。但是我只测了最高的两个树就ac了。。。样例太水了?还是正解就是如此?有待讨论。

 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
",b[i]);
70     }
71     return 0;
72 }
View Code

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...这样可以使得子串种类尽量少。

 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?'
':' ');
47         }
48     }
49     return 0;
50 }
View Code

http://acm.hust.edu.cn/vjudge/contest/view.action?cid=96950#problem/E

题意:给abc三个数,之间有两个符号,+-*,问可得到最小值。

解法:枚举3*3=9种情况。

 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
",solve());
44     }
45     return 0;
46 }
View Code

http://acm.hust.edu.cn/vjudge/contest/view.action?cid=96950#problem/F

题意:定义p(u,v)为u,v两点距离,定义p(u,v,w)= pvu) + pvw) + puw),求多少对uv满足v ≠ u 并且pvu) ≥ pvuw) 对于所有的 w。

解法:根据要求可以发现,必须是所有点都共线,且最两端的点,才能满足恰好相等,可以由三角形两边和大于第三边证明。

 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
",p[0].pid,p[n-1].pid);
57     }
58     return 0;
59 }
View Code

G http://acm.hust.edu.cn/vjudge/contest/view.action?cid=96950#problem/G

题意:给n堆石头,每堆都是奇数个,D和S轮流玩,D先玩,每次玩家可以选一堆石头,将其分为3堆且每堆都是奇数,最后谁没法分就输。

解法:发现一堆 a 个石头能被分 a/2 向下取整次。统计一下能分的次数的奇偶就知道胜负。

 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 }
View Code

H http://acm.hust.edu.cn/vjudge/contest/view.action?cid=96950#problem/H

题意:输入n条竖线m条横线,每条横线有权值,从左上角走到右下角,花费定义为路径上最小权值,求最大花费。

解法:答案只会从四种情况中产生,一是第一条竖线和最后一条横线,二是第一条横线和最后一条竖线,三是第一条和最后一条竖线加权值最大的横线,四是反之亦然。

 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
",solve());
61     }
62     return 0;
63 }
View Code

 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要喜欢,就是因子的个数要是素数。

 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
",solve());
92     }
93     return 0;
94 }
View Code

http://acm.hust.edu.cn/vjudge/contest/view.action?cid=96950#problem/J

题意:输入n个ABP串,可能是ABP的非空子序列,每次可以加一段连续的A or B or P,对于某一个串,必须按照ABP的顺序添加。问如何排列使得加的次数最小。

解法:先把串分类,同类放一起,一共7个情况,然后7的全排列验证这个排列需要加几次,取最小值。

  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
",solve());
135         for(int i=0;i<n;i++){
136             printf("%d%c",answer[i],i==n-1?'
':' ');
137         }
138     }
139     return 0;
140 }
View Code

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个方向都可以转移。

 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
",solve());
93     }
94     return 0;
95 }
View Code

L  http://acm.hust.edu.cn/vjudge/contest/view.action?cid=96950#problem/L

题意:输入n场比赛名字,时间,题数,提交数,每次提交的题号,结果,最后比赛名字时间原样输出,没提交的题输出. 提交通过输出o 未通过X。

解法:模拟题,怎么说怎么做。

  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=='
') 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 }
View Code

end

原文地址:https://www.cnblogs.com/gaolzzxin/p/4918018.html