---恢复内容开始---

A:哭泣的阿木木

  题目链接:http://csustacm.com:4803/contest/26/problem/J

  思路:这是一个很裸的线段树+lazy数组标记,直接用板子就可以了,数据很大很多,所以开long long,并且用scanf,printf输入输出。

  代码如下:

  1 #include <iostream>2 #include <algorithm>3 #include <cstdio>4 #include <cmath>5 using namespace std;6 long long a[1000010];7 long long tree[4000010];8 long long lazy[4000010];9 void pushup(int num) {10     tree[num]=tree[num<<1]+tree[num<<1|1];11     return ;12 }13 14 void pushdown(int l,int r,int num) {15     int mid=(l+r)>>1;16     if(lazy[num]) {17         tree[num<<1] += (lazy[num]*(mid-l+1));18         tree[num<<1|1] += (lazy[num]*(r-mid));19         lazy[num<<1] +=lazy[num];20         lazy[num<<1|1] +=lazy[num];21     }22     lazy[num] = 0 ;23     return ;24 }25 26 void build(int l,int r,int num) {27     if(l==r) {28         tree[num]=a[l];29         return ;30     }31     int mid = (l+r) >>1;32     build(l,mid,num<<1);33     build(mid+1,r,num<<1|1);34     pushup(num);35 }36 37 void quriy(int l,int r,int le,int ri,int num,long long& ans) {38     if(l>ri||r<le) return ;39     if(le<=l&&r<=ri) {40         ans+=tree[num];41         return ;42     }43     pushdown(l,r,num);44     int mid = (l+r)>>1;45     if(mid>=le) quriy(l,mid,le,ri,num<<1,ans);46     if(mid<ri) quriy(mid+1,r,le,ri,num<<1|1,ans);47     pushup(num);48     return ;49 }50 51 void modify(int l,int r,int le,int ri,int num,long long mods) {52     if(l>ri||r<le) return ;53     if(le<=l&&r<=ri) {54         lazy[num]+=mods;55         tree[num] += mods*(r-l+1);56         return ;57     }58     pushdown(l,r,num);59     int mid = (l+r) >>1;60     if(mid>=le) modify(l,mid,le,ri,num<<1,mods);61     if(mid<ri) modify(mid+1,r,le,ri,num<<1|1,mods);62     pushup(num);63     return ;64 }65 66 int main() {67     int n,q;68     scanf("%d%d",&n,&q);69     for(int i=1;i<=n;i++) {70         scanf("%lld",&a[i]);71     }72     build(1,n,1);73     char ss[10];74     int cmd;75     int  le,ri;76     long long k;77     while(q--) {78         scanf("%1s%d",ss,&cmd);79         if(cmd==1) {80             scanf("%d%d%lld",&le,&ri,&k);81             modify(1,n,le,ri,1,k);82         }83         else if(cmd==2) {84             scanf("%d%d%lld",&le,&ri,&k);85             modify(1,n,le,ri,1,-k);86         }87         else if(cmd==3) {88             scanf("%d%lld",&le,&k);89             ri=le;90             long long ans=0;91             quriy(1,n,le,le,1,ans);92             modify(1,n,le,le,1,k-ans);93         }94         else {95             scanf("%d%d",&le,&ri);96             long long  ans=0;97             quriy(1,n,le,ri,1,ans);98             cout<<ans<<endl;99         }
100     }
101     return 0;
102 }

View Code

  

B:点进来吧,这里有你想要的

  题目链接:http://10.64.70.166/contest/27/problem/I

  思路:可以看成只有两个物品的背包问题,用DP来解决,dp动态移动方程为:dp[i]=dp[i-1]+dp[i-m] . 表示高兴度为 i 所拥有的方案数为高兴度为  i-1 的方案数(即再吃一个小食) 加上高兴度为 i-m 的方案数(即再吃一个汉堡).

    需要注意的是因为吃小食和吃汉堡的顺序不同会被算为不同的方案数,所以要是先枚举物品,再枚举高兴度会少算。

  代码如下:

 1 #include <iostream>
 2 #include <algorithm>
 3 using namespace std;
 4
 5 long long dp[200050];
 6 const long long mod = 1e8+7;
 7
 8 int main() {
 9     int t;
10     cin>>t;
11     while(t--) {
12         int n,m;
13         cin>>n>>m;
14         for(int i=0;i<=n;i++) dp[i]=0;
15         dp[0]=1;
16         for(int i=1;i<=n;i++) {//先枚举高兴度
17             if(i>=1) {//如果能吃小食就加上吃小食之前的方案数.
18                 dp[i] = (dp[i]%mod+dp[i-1]%mod)%mod;
19             }
20             if(i>=m) {//同上
21                 dp[i] = (dp[i]%mod+dp[i-m]%mod)%mod;
22             }
23         }
24         cout<<dp[n]<<endl;
25     }
26     return 0;
27 }

View Code

 

C:寻宝

  题目链接:http://10.64.70.166/contest/27/problem/E

  思路:读完题可能感觉是道比较难的题,我们可以先考虑只有两个人寻宝的所有情况(即每种宝藏都只有两个).如图下这种情况下,我们可以知道a1走向b2,a2走向b2的方法是最优的(其他走法会多走a2-a1之间的距离),其他情况大家可以

    例举,可以得出最小的走最小一定是最短的走法. 那这样这道题就是一道很明显的贪心题,数据范围也不大,只要注意求绝对值和开long long即可。

    

  代码如下:

 1 #include <iostream>
 2 #include <algorithm>
 3 #include <cmath>
 4 using namespace std;
 5 long long a[110][10];
 6
 7
 8 int main() {
 9     int n,k;
10     cin>>n>>k;
11     for(int i=0;i<n;i++) {
12         for(int j=0;j<k;j++) {
13             cin>>a[i][j];
14         }
15         sort(a[i],a[i]+k);//讲每种宝藏从小到大排序.
16     }
17     long long ans=0;
18     for(int j=0;j<k;j++) {
19         for(int i=1;i<n;i++) {
20             ans += abs(a[i][j]-a[i-1][j]);//最小的走最小的.
21         }
22     }
23     cout<<ans<<endl;
24     return 0;
25 }

View Code

D:武器大师的宝贝

  题目链接:http://10.64.70.166/contest/27/problem/D

  思路:如果了解位运算符 ^ 的话这道题很显然是求两个区间的相重合的部分,代码很简单但是细节很多,比如要输出最简形式,所以我们要用欧几里得算法求分子和分母的最大公约数。

  代码如下:

 1 #include <iostream>
 2 #include <algorithm>
 3 using namespace std;
 4
 5 long long gcd(long long a,long long b) {
 6     return b==0? a:gcd(b,a%b);
 7 }
 8
 9 int main() {
10     int t;
11     cin>>t;
12     while(t--) {
13         long long a,b,c,d;
14         cin>>a>>b>>c>>d;
15         if(a>c) {
16             swap(a,c);
17             swap(b,d);
18         }
19         if(b<c) cout<<"0/1"<<endl; //判断两个区间有没有交集.
20         else {
21             long long di = (b-a+1)*(d-c+1);
22             long long ss = min(b,d)-max(a,c)+1;
23             cout<<ss/gcd(ss,di)<<'/'<<di/gcd(ss,di)<<endl;
24         }
25     }
26     return 0;
27 }

View Code

E:千万别点进来,点进来你就哭了

  题目链接:http://10.64.70.166/contest/27/problem/F

  思路:n次求最短路,到所有点和最小的那次最短路就是我们要求的结果,最短路用disjike的要用优先队列优化,否则会tle。

  代码如下:

 1 #include <iostream>
 2 #include <algorithm>
 3 #include <vector>
 4 #include <queue>
 5 #define inf 1e18
 6 using namespace std;
 7 priority_queue<struct node> q;
 8 long long d[1100];
 9 long long ans;
10 int ans_num;
11 int vis[1100];
12 int n,m;
13 struct Next {
14     int tos;long long val;
15
16     Next(int tos=0,long long val=0) {
17         this->tos = tos;
18         this->val = val;
19     }
20 };
21 struct Next s;
22 vector<Next> to[1100];
23
24 struct node {
25     int num;
26     long long dis;
27     bool operator < (const node& a) const {
28         return a.dis<=this->dis;
29     }
30     node(int num=0,long long dis = 0) {
31         this->num = num;
32         this->dis = dis;
33     }
34 };
35
36 int disjike(int st) {
37     while(!q.empty()) q.pop();
38     for(int i=1;i<=n;i++) {
39         d[i]=inf;
40         vis[i]=0;
41     }
42     d[st]=0;
43     vis[st]=1;
44     int nums=to[st].size();
45     for(int i=0;i<nums;i++) {
46         d[to[st][i].tos] = to[st][i].val;
47         struct node nodes = node(to[st][i].tos,d[to[st][i].tos]);
48         q.push(nodes);
49     }
50     for(int j=0;;j++) {
51         if(q.empty()) break;
52         struct node x=q.top();
53         q.pop();
54         int nums=to[x.num].size();
55         if(vis[x.num]==1) continue;
56         if(d[x.num]==inf) continue;
57         vis[x.num]=1;
58         for(int i=0;i<nums;i++) {
59             if(d[to[x.num][i].tos] > d[x.num]+to[x.num][i].val) {
60                 d[to[x.num][i].tos]=d[x.num]+to[x.num][i].val;
61                 q.push(node(to[x.num][i].tos,d[to[x.num][i].tos]));
62             }
63         }
64     }
65     long long sum=0;
66     for(int i=1;i<=n;i++) {
67         sum+=d[i];
68     }
69     if(sum<=ans) {
70         ans=sum;
71         ans_num=st;
72     }
73     return 0;
74 }
75
76
77 int main() {
78     while(cin>>n>>m) {
79         ans=inf;
80         for(int i=1;i<=n;i++) to[i].clear();
81         for(int i=0;i<m;i++) {
82             int a,b;long long c;
83             cin>>a>>b>>c;
84             s=Next(a,c);
85             to[b].push_back(s);
86             s.tos=b;
87             to[a].push_back(s);
88         }
89         for(int i=n;i>=1;i--) {
90             disjike(i);
91         }
92         cout<<ans<<' '<<ans_num<<endl;
93     }
94     return 0;
95 }

View Code

F:提莫队长正在待命!

  题目链接:http://10.64.70.166/contest/27/problem/B

  思路:可以利用并查集解决,没有蘑菇的话就合并,有蘑菇就不合并,最后会得到几个集合,A集合的点走到B集合的点中时一定会经过他们之间那条有蘑菇的路(路径数就等于 A.size()*B.size() ),要求的结果就是所有集合走到其他集合所需路径数之和。

  代码如下:

 1 #include <iostream>
 2 #include <algorithm>
 3 using namespace std;
 4 int f[300050];
 5 long long q[300050]={0};
 6 int finds(int x) {
 7     return f[x]==x? x:f[x]=finds(f[x]);
 8 }
 9
10 int unions(int x,int y) {
11     x=finds(x);
12     y=finds(y);
13     if(x==y) return 0;
14     else {
15         f[x]=y;
16     }
17     return 0;
18 }
19
20
21 int main() {
22     int n;
23     cin>>n;
24     for(int i=1;i<=n;i++) f[i]=i;
25     for(int i=0;i<n-1;i++) {
26         int a,b,c;
27         cin>>a>>b>>c;
28         if(c==1) continue;
29         else {
30             unions(a,b);
31         }
32     }
33     long long ans=0;
34     for(int i=1;i<=n;i++) {
35         q[finds(i)]++;
36     }
37     for(int i=1;i<=n;i++) {
38         if(q[i]) ans += (q[i]*(n-q[i]));
39     }
40     cout<<ans<<endl;
41     return 0;
42 }

View Code

G:凛冬将至

  题目链接:http://10.64.70.166/contest/27/problem/C

  思路:LCA板子+枚举所有情况,即不使用密道的距离,使用密道(两种,起点->u->v->终点或起点->v->u->终点)的距离.

  代码如下:

 1 #include <iostream>
 2 #include <vector>
 3 #include <cmath>
 4 #define maxn 100009
 5 using namespace std;
 6 int n,N;
 7
 8 struct edge{
 9     int from,to,w;
10 };
11 edge edges[maxn<<1];
12 vector<int> G[maxn];
13
14 int dp[maxn][100]={0},gw[maxn][100]={0};
15 int depth[maxn];
16
17 void dfs(int x) {
18     for(int i=1;i<=N;i++) {
19         dp[x][i]=dp[dp[x][i-1]][i-1];
20         gw[x][i]=gw[x][i-1]+gw[dp[x][i-1]][i-1];
21     }
22     for(int i=0;i<G[x].size();i++) {
23         edge  e = edges[G[x][i]];
24  ​           depth[e.to]=depth[x]+1;
25             dp[e.to][0]=x;
26             gw[e.to][0]=e.w;
27             dfs(e.to);
28         }
29     }
30 }
31
32 int lca(int a,int b) {
33     if(a==b) return 0;
34     if(depth[a]>depth[b]) swap(a,b);
35     int ans=0;
36     for(int i = N;i>=0;i--) {
37         if(depth[a] < depth[b] && depth[dp[b][i]] >= depth[a]) ans+=gw[b][i],b=dp[b][i];
38     }
39     for(int j=N;j>=0;j--) {
40         if(dp[a][j]!=dp[b][j]) {
41             ans+=gw[a][j];
42             ans+=gw[b][j];
43             a=dp[a][j];
44             b=dp[b][j];
45         }
46     }
47     if(a!=b) {
48         ans+=gw[a][0],ans+=gw[b][0];
49     }
50     return ans;
51 }
52
53 int main() {
54     cin>>n;
55     for(int i=0;i<2*(n-1);i+=2) {
56         int a,b,c;
57         cin>>a>>b>>c;
58         edges[i].from=a;
59         edges[i].to=b;
60         edges[i].w=c;
61         edges[i+1].from=b;
62         edges[i+1].to=a;
63         edges[i+1].w=c;
64         G[a].push_back(i);
65         G[b].push_back(i+1);
66     }
67     N = log(n+0.0)/log(2.0);
68     depth[1]=0;
69     dfs(1);
70     int le,ri,val;
71     cin>>le>>ri>>val;
72     int q;
73     cin>>q;
74     while(q--) {
75         int as,bs;
76         cin>>as>>bs;
77         int ans=lca(as,bs);
78         ans=min(ans,min(lca(as,le)+val+lca(ri,bs),lca(bs,le)+val+lca(ri,as)));
79         cout<<ans<<endl;
80     }
81     return 0;
82 }

View Code

H:小明买年糕

  题目链接:http://10.64.70.166/contest/27/problem/H

  思路:二分W,因为可能区间数较多,所以我们可以用前缀和优化,这样就能复杂度o(n+q)情况下完成一次判断.

  代码如下:

 1 #include <iostream>
 2 #include <cmath>
 3 #define inf 1e18
 4 using namespace std;
 5 int n,m;
 6 long long s;
 7 long long w[200010],v[200010];
 8 long long qu[200010][2];
 9 long long sum[200010];
10 long long num[200010];
11 long long ans=inf;
12
13 long long is_ok(long long x) {
14     long long anss=0;
15     sum[0]=0;
16     num[0]=0;
17     for(int i=1;i<=n;i++) {
18         if(w[i]>=x) {
19             sum[i]=sum[i-1]+v[i];
20             num[i]=num[i-1]+1;
21         }
22         else {
23             sum[i]=sum[i-1];
24             num[i]=num[i-1];
25         }
26     }
27
28     for(int i=0;i<m;i++) {
29
30         anss+=(sum[qu[i][1]]-sum[qu[i][0]-1])*(num[qu[i][1]]-num[qu[i][0]-1]);
31
32     }
33     if(abs(anss-s)<ans) {
34         ans=abs(anss-s);
35     }
36     return anss;
37 }
38
39 int main() {
40
41     long long  l=0,r=0;
42     cin>>n>>m>>s;
43     for(int i=1;i<=n;i++) {
44         cin>>w[i]>>v[i];
45         r=max(w[i],r);
46     }
47     for(int i=0;i<m;i++) {
48         cin>>qu[i][0]>>qu[i][1];
49     }
50     while(l<=r) {
51         long long mid =(l+r) >> 1;
52         if(is_ok(mid)<s) {
53             r=mid-1;
54         }
55         else {
56             l=mid+1;
57         }
58     }
59     is_ok(l-1);
60     is_ok(l+1);
61     cout<<ans<<endl;
62     return 0;
63 }

View Code

I:可怜的ljb

  题目链接:http://10.64.70.166/contest/27/problem/G

  思路:线段树/树状数组求逆序对

  代码如下:

 1 #include <iostream>
 2
 3 using namespace std;
 4 int c[100010];
 5 int n;
 6 int a[100010];
 7 void init(int n) {
 8     for(int i=1;i<=n;i++) c[i]=0;
 9 }
10
11 int lowbit(int x) {
12     return x&-x;
13 }
14
15 void update(int pos,int d) {
16     while(pos<=n) {
17         c[pos]+=d;
18         pos += lowbit(pos);
19     }
20     return ;
21 }
22
23 int getsum(int x) {
24     int sum=0;
25     while(x>0) {
26         sum+=c[x];
27         x-=lowbit(x);
28     }
29     return sum;
30 }
31
32 int main() {
33     int t;
34     cin>>t;
35     while(t--) {
36         long long ans=0;
37         cin>>n;
38         init(n);
39         for(int i=1;i<=n;i++) {
40             int s;
41             cin>>s;
42             a[s]=i;
43         }
44         for(int i=1;i<=n;i++) {
45             int s;
46             cin>>s;
47             ans+= (long long )getsum(n)-getsum(a[s]);
48             update(a[s],1);
49         }
50         cout<<ans<<endl;
51     }
52     return 0;
53 }

View Code

J:“一个部族,一个民族,一个弗雷尔卓德。”

  题目链接:http://10.64.70.166/contest/27/problem/A

  思路:线性筛+树状数组,题目要求的求所有小于数n的并且最小素数小于或等于n的最小素数的数的总数,我们在利用线性筛筛到数n时,最小素数小于或等于n的最小素数的数一定是被筛完了的,所以我们只要判断小于n的数已经筛过多少就可以了.

  代码如下:

 1 #include <iostream>
 2 #include <cstdio>
 3 #define maxn 1000000
 4 using namespace std;
 5 int c[1000010]={0};
 6 int vis[1000010]={0};
 7 int ans[1000010]={0};
 8
 9 int lowbit(int  x) {
10     return x&-x;
11 }
12
13 void update(int pos,int d) {
14     while(pos<=maxn) {
15         c[pos]+=d;
16         pos+=lowbit(pos);
17     }
18     return ;
19 }
20
21 int getsum(int pos) {
22     int ans=0;
23     while(pos>0) {
24         ans+=c[pos];
25         pos-=lowbit(pos);
26     }
27     return ans;
28 }
29
30
31
32 int main() {
33     update(1,1);
34     for(int i=2;i<=maxn;i++) {
35         if(vis[i]!=0) continue;
36         int k=i;
37         while(k<=maxn) {
38             if(vis[k]!=0) {
39                 k+=i;
40                 continue;
41             }
42             ans[k]=getsum(k);
43             vis[k]=1;
44             update(k,1);
45             k+=i;
46         }
47     }
48     int t;
49     scanf("%d",&t);
50     while(t--) {
51         int n;
52         scanf("%d",&n);
53         printf("%d\n",ans[n]);
54     }
55     return 0;
56 }

View Code

转载于:https://www.cnblogs.com/no-bb-qu-shua-ti/p/10480935.html

CSUST选拔赛题解相关推荐

  1. CSUST选拔赛题解之-Problem H: 逃出监狱

    Problem H: 逃出监狱 Time Limit: 1 Sec  Memory Limit: 128 MB Submit: 116  Solved: 42 [Submit][Status][Web ...

  2. CSUST选拔赛题解之-Problem C: 先有durong后有天

    Problem C: 先有durong后有天 Time Limit: 3 Sec  Memory Limit: 128 MB Submit: 59  Solved: 16 [Submit][Statu ...

  3. 北京信息科技大学第十三届程序设计竞赛暨ACM选拔赛题解

    北京信息科技大学第十三届程序设计竞赛暨ACM选拔赛题解 A lzh的蹦床 B 所谓过河 C 旅行家问题1 D 旅行家问题2 E 小菲和Fib数列 F 好玩的音乐游戏 G ranko的手表 H 字母收集 ...

  4. XMU区域赛选拔赛题解

    XMU区域赛选拔赛题解 B.是谁打了奶奶 Description 最近发生了一起骇人听闻的打奶奶事件,凶手就是--惊奇队长. 惊奇队长是在电车上打的奶奶,那么我们就来看一个和电车有关的问题. 某市修建 ...

  5. CSUST 集训队选拔赛题解

    选拔赛的题解,~~~ 题目链接:请点击 A题 素数筛 + 线段树(树状数组) 先用素数筛打表,然后线段树更新,遍历求出值,O(1)查询即可 AC代码: /*num数组 是把记录 数是否存在 存在即为1 ...

  6. 2018 焦作站亚洲区域赛校内选拔赛题解

    SUST_2018 焦作站亚洲区域赛校内选拔赛 A.高速        by yoyo tag:图论.最短路 //最短路 #include<bits/stdc++.h> using nam ...

  7. 2018中国大学生程序设计竞赛-网络选拔赛题解

    以下所有AC题解程序来自"仙客传奇"团队. A. Buy and Resell AC的C++语言程序: #include<iostream> #include<c ...

  8. SUST_2018 焦作站亚洲区域赛校内选拔赛题解

    SUST_2018 焦作站亚洲区域赛校内选拔赛 A.高速        by yoyo tag:图论.最短路 //最短路 #include<bits/stdc++.h> using nam ...

  9. csust2019集训队选拔赛题解

    第一次参加比赛 崩的实在是太惨了.. 只A了一道板子题(已经被自己菜哭了 没想到大家都掉线了 一起崩 这也给了我一个血的教训 以后比赛一定要多开几题 简直是在死撑着坐满五个小时 当时其实老早就想溜了( ...

最新文章

  1. 自定义spring kafka consumer 线程池
  2. 部署harbor1.2.0开启ldap验证
  3. 11.C程序内存空间分配
  4. Office 插件开发和部署的总结
  5. GraphPad Prism软件无响应问题解决办法
  6. 王朔《我的千岁寒》:可以看却无法看到
  7. Netty Java快速指南
  8. 八邻域轮廓跟踪算法_结合mRMR选择和IFCM聚类的遥感影像分类算法
  9. ES6--Let 和 const 命令
  10. Cognos 优化-大数据量的报表
  11. SEO小白学习与实践(一):seo学习缘起、目标
  12. 阿里Maven仓库不限容量,免费用
  13. 学生成绩分析系统后端函数解释(Python)
  14. ios零基础学习 准备什么,如何去学习
  15. android 获取设备的mac地址,Android编程获取设备MAC地址的实现方法
  16. PHP设计模式(1)
  17. 2.企业发放的奖金根据利润提成。
  18. 模式窗口window.showModalDialog()的用法
  19. Shell学习(12)文件操作
  20. Windows文件服务器文件审计,文件监控软件,File_System_Auditor2.53安装教程

热门文章

  1. Unity加载C语言32dll,Unity3d 载入 C++/CLI (托管方式c++) 的动态库(DLL)
  2. 感谢郁金香老师把我带入编写辅助的大门
  3. 乳牛咳嗽声与呼吸系统疾病的关系(译全文)
  4. 突破自己,挑战10K
  5. 科技人文丨太在意别人评价怎么办?
  6. 株洲北大青鸟毕业感言
  7. AI智能安防视频EasyCVR平台接入国标硬件设备播放视频失败的原因排查与分析
  8. pdf转换为可编辑的ppt文件的方法
  9. 什么是MVC模式?MVC三层架构的含义和作用?
  10. linux系统fsck.ext4,linux – 如何在fsck之后恢复损坏的ext4文件系统?