Gym 101915

Gym - 101915A  Printing Books

题意:有一本书,从第X页开始,一共用了n位数字,求此书一共多少页。99就是两位数字,100就是三位数字。

思路:直接模拟即可,我用了一个high和一个low,因为我把数字按位数分成了几个部分,1-9,10-99,100-999等(实际上high会等于1000),这样就会low = 100,high = 999之类的了,如果遇到边界,比如刚开始时,low和high有所调整,比如low=x,high=999,以方便计算。

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<vector>
 4 #include<stack>
 5 #include<queue>
 6 #include<map>
 7 #include<set>
 8 #include<cstdio>
 9 #include<cstring>
10 #include<cmath>
11 #include<ctime>
12 #define fuck(x) cout<<#x<<" = "<<x<<endl;
13 #define ls (t<<1)
14 #define rs ((t<<1)+1)
15 using namespace std;
16 typedef long long ll;
17 typedef unsigned long long ull;
18 const int maxn = 100086;
19 const int inf = 2.1e9;
20 const ll Inf = 999999999999999999;
21 const int mod = 1000000007;
22 const double eps = 1e-6;
23 const double pi = acos(-1);
24 
25 ll pre[20];
26 ll num[20];
27 ll get_n(ll x)
28 {
29     ll ans = 0;
30     while(x){
31         x/=10;
32         ans++;
33     }
34     return ans;
35 }
36 
37 int main()
38 {
39     int T;
40     scanf("%d",&T);
41     while(T--){
42         ll n,x;
43         scanf("%lld%lld",&n,&x);
44         ll di =get_n(x);
45         ll low = x;
46         ll high=1;
47         for(int i=1;i<=di;i++){
48             high*=10;
49         }
50         ll ans= 0;
51         for(int i=di;i<=16;i++){
52             ll t = (high - low)*i;
53             if(t<=n){n-=t;ans+=high-low;}
54             else{
55                 if(n%i==0){ans+=n/i;}
56                 else{ans=-1;}break;
57             }
58             low = high;
59             high*=10;
60         }
61         printf("%lld
",ans);
62     }
63     return 0;
64 }
View Code

 

Gym - 101915B Ali and Wi-Fi

题意:Ali要去蹭WIFI,他可以同时蹭m个WIFI,每个WIFI有一个信号值,以及自己的坐标和信号半径,Ali可以获得的WIFI信号值就是蹭到的WIFI的代数和。Ali可以出现在任何位置,求Ali最多得到的信号值是多大。

思路:最后的答案一定在一个圆交的区域内取得,现在的问题就是如何找到这个区域,由于是浮点数,枚举是不可能的,但是我们起码可以知道,圆的交点一定在某个圆交的边界上,所以我们只需要枚举每个圆的交点,再判断交点的信号值的大小就可以得出答案了,但是考虑到内含这种情况,所以再把所有的圆心判断一遍。

求圆交的地方我抄了别人的板子,但是这板子有点长了,可能不是很适合在赛场上使用。还有不知道为什么,这板子用了using namespace std 会错,我也不知道为什么、

c语言--求两圆交点

#include<iostream>
#include<algorithm>
#include<vector>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<ctime>
#define fuck(x) std::cout<<#x<<" = "<<x<<std::endl;
#define ls (t<<1)
#define rs ((t<<1)+1)
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 100086;
const int inf = 2.1e9;
const double eps = 1e-10;

struct circle
{
    double x,y;
    double r,w;
}c[300];
struct point
{
    double x,y;
}p[maxn];
int n,m;
int top = 0;

struct point_t {
    double x, y;
};

struct circle_t {
    struct point_t center;
    double r;
};

int double_equals(double const a, double const b)
{
    static const double ZERO = 1e-9;
    return fabs(a - b) < ZERO;
}

double distance_sqr(struct point_t const* a, struct point_t const* b)
{
    return (a->x - b->x) * (a->x - b->x) + (a->y - b->y) * (a->y - b->y);
}

double distance(struct point_t const* a, struct point_t const* b)
{
    return sqrt(distance_sqr(a, b));
}

int insect(struct circle_t circles[], struct point_t points[])
{
    double d, a, b, c, p, q, r;
    double cos_value[2], sin_value[2];
    if (double_equals(circles[0].center.x, circles[1].center.x)
        && double_equals(circles[0].center.y, circles[1].center.y)
        && double_equals(circles[0].r, circles[1].r)) {
        return -1;
    }

    d = distance(&circles[0].center, &circles[1].center);
    if (d > circles[0].r + circles[1].r
        || d < fabs(circles[0].r - circles[1].r)) {
        return 0;
    }

    a = 2.0 * circles[0].r * (circles[0].center.x - circles[1].center.x);
    b = 2.0 * circles[0].r * (circles[0].center.y - circles[1].center.y);
    c = circles[1].r * circles[1].r - circles[0].r * circles[0].r
        - distance_sqr(&circles[0].center, &circles[1].center);
    p = a * a + b * b;
    q = -2.0 * a * c;
    if (double_equals(d, circles[0].r + circles[1].r)
        || double_equals(d, fabs(circles[0].r - circles[1].r))) {
        cos_value[0] = -q / p / 2.0;
        sin_value[0] = sqrt(1 - cos_value[0] * cos_value[0]);

        points[0].x = circles[0].r * cos_value[0] + circles[0].center.x;
        points[0].y = circles[0].r * sin_value[0] + circles[0].center.y;

        if (!double_equals(distance_sqr(&points[0], &circles[1].center),
                           circles[1].r * circles[1].r)) {
            points[0].y = circles[0].center.y - circles[0].r * sin_value[0];
        }
        return 1;
    }

    r = c * c - b * b;
    cos_value[0] = (sqrt(q * q - 4.0 * p * r) - q) / p / 2.0;
    cos_value[1] = (-sqrt(q * q - 4.0 * p * r) - q) / p / 2.0;
    sin_value[0] = sqrt(1 - cos_value[0] * cos_value[0]);
    sin_value[1] = sqrt(1 - cos_value[1] * cos_value[1]);

    points[0].x = circles[0].r * cos_value[0] + circles[0].center.x;
    points[1].x = circles[0].r * cos_value[1] + circles[0].center.x;
    points[0].y = circles[0].r * sin_value[0] + circles[0].center.y;
    points[1].y = circles[0].r * sin_value[1] + circles[0].center.y;

    if (!double_equals(distance_sqr(&points[0], &circles[1].center),
                       circles[1].r * circles[1].r)) {
        points[0].y = circles[0].center.y - circles[0].r * sin_value[0];
    }
    if (!double_equals(distance_sqr(&points[1], &circles[1].center),
                       circles[1].r * circles[1].r)) {
        points[1].y = circles[0].center.y - circles[0].r * sin_value[1];
    }
    if (double_equals(points[0].y, points[1].y)
        && double_equals(points[0].x, points[1].x)) {
        if (points[0].y > 0) {
            points[1].y = -points[1].y;
        } else {
            points[0].y = -points[0].y;
        }
    }
    return 2;
}

void solve(int i,int j)
{
    struct circle_t circles[2];
    struct point_t points[2];
    circles[0].center.x=c[i].x;circles[0].center.y=c[i].y;circles[0].r=c[i].r;
    circles[1].center.x=c[j].x;circles[1].center.y=c[j].y;circles[1].r=c[j].r;

    switch (insect(circles, points)) {
        case -1:
            return;
        case 0:
            return;
        case 1:{
            ++top;
            p[top].x=points[0].x;
            p[top].y=points[0].y;
            return;}
        case 2:{
            ++top;
            p[top].x=points[0].x;
            p[top].y=points[0].y;
            ++top;
            p[top].x=points[1].x;
            p[top].y=points[1].y;
        }
    }
}

double cal(int i)
{
    double ans = 0;
    std::priority_queue<double>num;
    for(int j=1;j<=n;j++){
        double d1 = (c[j].x-p[i].x)*(c[j].x-p[i].x)+ (c[j].y-p[i].y)*(c[j].y-p[i].y);
        double d2 = 1.0*c[j].r*c[j].r;
        if(d2-d1>=-eps){num.push(c[j].w);}
    }
    for(int j=1;j<=m;j++){
        if(num.empty()){break;}
        ans+=num.top();
        num.pop();
    }
    return ans;
}


int main()
{
    int T;
    scanf("%d",&T);
    while(T--){
        top=0;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++){
            scanf("%lf%lf%lf%lf",&c[i].x,&c[i].y,&c[i].r,&c[i].w);
            top++;
            p[top].x = c[i].x;
            p[top].y = c[i].y;
        }
        for(int i=1;i<=n;i++){
            for(int j=i+1;j<=n;j++){
                solve(i,j);
            }
        }
        double ans =0;
        for(int i=1;i<=top;i++){
            ans = std::max(ans,cal(i));
        }
        printf("%.0f
",ans);
    }
    return 0;
}
View Code

 

Gym - 101915C Shahhoud Training Hussain 

题意:每天可以得到P个题,但是只能做k个,问n天后还有多少个题没有做

思路:注意k>p的情况

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<vector>
 4 #include<stack>
 5 #include<queue>
 6 #include<map>
 7 #include<set>
 8 #include<cstdio>
 9 #include<cstring>
10 #include<cmath>
11 #include<ctime>
12 #define fuck(x) cout<<#x<<" = "<<x<<endl;
13 #define ls (t<<1)
14 #define rs ((t<<1)+1)
15 using namespace std;
16 typedef long long ll;
17 typedef unsigned long long ull;
18 const int maxn = 100086;
19 const int inf = 2.1e9;
20 const ll Inf = 999999999999999999;
21 const int mod = 1000000007;
22 const double eps = 1e-6;
23 const double pi = acos(-1);
24 
25 int main()
26 {
27     int T;
28     scanf("%d",&T);
29     ll k,p,n;
30     while(T--){
31         scanf("%lld%lld%lld",&k,&p,&n);
32         ll ans =max(0ll,k-p)*n;
33         printf("%lld
",ans);
34     }
35     return 0;
36 }
View Code

Gym - 101915D Largest Group

题意:给一个图,求最大团。

思路:图的最大团 = 补图的最大独立集

  二分图的最大独立集 = 顶点个数 - 最大匹配数

  原图的补图正好是二分图。直接上DFS会超时,虽然我的代码在普通图上面已经跑得很快了。

  要说这两条公式的证明,我也不太会。。。。

  1 #include<iostream>
  2 #include<algorithm>
  3 #include<vector>
  4 #include<stack>
  5 #include<queue>
  6 #include<map>
  7 #include<set>
  8 #include<cstdio>
  9 #include<cstring>
 10 #include<cmath>
 11 #include<ctime>
 12 #define fuck(x) cout<<#x<<" = "<<x<<endl;
 13 #define ls (t<<1)
 14 #define rs ((t<<1)+1)
 15 using namespace std;
 16 typedef long long ll;
 17 typedef unsigned long long ull;
 18 const int maxn = 100086;
 19 const int inf = 2.1e9;
 20 const ll Inf = 999999999999999999;
 21 const int mod = 1000000007;
 22 const double eps = 1e-6;
 23 const double pi = acos(-1);
 24 
 25 struct edge
 26 {
 27     int v,next,w;
 28 }e[5000];
 29 int head[500],cur;
 30 int T;
 31 int n,m;
 32 int mp[500][500];
 33 int sx,ex;
 34 
 35 void add(int x,int y)
 36 {
 37     e[cur].v=y;
 38     e[cur].w=1;
 39     e[cur].next=head[x];
 40     head[x]=cur;
 41     cur++;
 42 
 43     e[cur].v=x;
 44     e[cur].w=0;
 45     e[cur].next=head[y];
 46     head[y]=cur;
 47     cur++;
 48 }
 49 
 50 void build()
 51 {
 52     cur=0;
 53     memset(mp,0,sizeof(mp));
 54     memset(head,-1,sizeof(head));
 55     int x,y;
 56 
 57     for(int i=1;i<=m;i++){
 58         scanf("%d%d",&x,&y);
 59         mp[x][y+n]=true;
 60     }
 61     for(int i=1;i<=n;i++){
 62         for(int j=n+1;j<=2*n;j++){
 63             if(!mp[i][j]){add(i,j);}
 64         }
 65     }
 66     for(int i=1;i<=n;i++){
 67         add(2*n+1,i);
 68         add(i+n,2*n+2);
 69     }
 70 }
 71 int book[500],num[500];
 72 bool bfs()
 73 {
 74     memset(book,0,sizeof(book));
 75     for(int i=1;i<=2*n+2;i++){
 76         num[i]=head[i];
 77     }
 78     queue<int>q;
 79     q.push(sx);
 80     book[sx]=1;
 81     int t,x;
 82     while(!q.empty()){
 83         t =q.front();
 84         q.pop();
 85         int k=head[t];
 86         while(k!=-1){
 87             x=e[k].v;
 88             if(!book[x]&&e[k].w){
 89                 book[x]=book[t]+1;
 90                 q.push(x);
 91             }
 92             k=e[k].next;
 93         }
 94     }
 95     return book[ex]!=0;
 96 }
 97 
 98 int dfs(int u,int f)
 99 {
100     if(u==ex){return f;}
101     int &k=num[u];
102     int sum=0;
103 
104     while(k!=-1){
105         if(book[e[k].v]==book[u]+1&&e[k].w){
106             int d = dfs(e[k].v,min(f,e[k].w));
107             f-=d;e[k].w-=d;e[k^1].w+=d;
108             sum+=d;
109         }
110         k=e[k].next;
111     }
112     return sum;
113 }
114 
115 int dinic()
116 {
117     int ans =0;
118     while(bfs()){
119         int f;
120         while((f=dfs(sx,inf))>0){
121             ans+=f;
122         }
123     }
124     return ans;
125 }
126 
127 int main()
128 {
129     int T;
130     scanf("%d",&T);
131     while(T--){
132         scanf("%d%d",&n,&m);
133         build();
134         sx =2*n+1;ex=2*n+2;
135         printf("%d
",2*n-dinic());
136     }
137     return 0;
138 }
View Code

 

Gym - 101915E Minesweeper

题意:玩扫雷啦!有一个r*c的格子,放置地雷有以下要求,1.每块空地周围的地雷不能超过m个 2.每个地雷傍边必有一个空地。求最多可以埋多少地雷。

思路:DFS,2的36次方也不是闹着玩的,但是可以加一些剪枝,这样便可以顺利AC

当时做的时候想到搜索但是被自己否定了,直到看到了这题解

传送门

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<vector>
 4 #include<stack>
 5 #include<queue>
 6 #include<map>
 7 #include<set>
 8 #include<cstdio>
 9 #include<cstring>
10 #include<cmath>
11 #include<ctime>
12 #define fuck(x) cout<<#x<<" = "<<x<<endl;
13 #define ls (t<<1)
14 #define rs ((t<<1)+1)
15 using namespace std;
16 typedef long long ll;
17 typedef unsigned long long ull;
18 const int maxn = 100086;
19 const int inf = 2.1e9;
20 const ll Inf = 999999999999999999;
21 const int mod = 1000000007;
22 const double eps = 1e-6;
23 const double pi = acos(-1);
24 bool mp[10][10];
25 int n,m,k;
26 int ans;
27 int to[8][2]={0,1,1,0,0,-1,-1,0,1,1,1,-1,-1,1,-1,-1};
28 bool check(int x,int y)
29 {
30     int cnt = 0;
31     int tx,ty;
32     if(mp[x][y]==0){
33         for(int i=0;i<8;i++){
34             tx = x+to[i][0];
35             ty = y+to[i][1];
36             if(mp[tx][ty]){
37                 cnt++;
38             }
39         }
40         if(cnt>k){return false;}
41         else return true;
42     }
43     for(int i=0;i<8;i++){
44         tx=x+to[i][0];
45         ty=y+to[i][1];
46         if(tx>0&&ty>0&&tx<=n&&ty<=m&&!mp[tx][ty]){return true;}
47     }
48     return false;
49 }
50 
51 void dfs(int x,int y,int cnt,int last)
52 {
53     if(cnt+last<=ans){return;}
54     if(x>n){
55         if(check(n,m))ans=max(ans,cnt);
56         return;
57     }
58     for(int i=0;i<=1;i++){
59         mp[x][y]=i;
60         if(x==n){
61             if(check(x-1,y-1)&&check(x,y-1)){
62                 if(y==m&&check(x-1,y)){
63                     dfs(x+1,1,cnt+i,last-1);
64                 }
65                 else if(y!=m){
66                     dfs(x,y+1,cnt+i,last-1);
67                 }
68             }
69         }
70         else if(y==m){
71             if(check(x-1,y-1)&&check(x-1,y)){
72                 dfs(x+1,1,cnt+i,last-1);
73             }
74         }
75         else{
76             if(check(x-1,y-1)){
77                 dfs(x,y+1,cnt+i,last-1);
78             }
79         }
80     }
81 }
82 
83 int main()
84 {
85     int T;
86     scanf("%d",&T);
87 
88     while(T--){
89         memset(mp,0,sizeof(mp));
90         ans=0;
91         scanf("%d%d%d",&n,&m,&k);
92         dfs(1,1,0,n*m);
93         printf("%d
",ans);
94     }
95 
96     return 0;
97 }
View Code

 

Gym - 101915F A Missing Problem in TCPC2017

题意:给你n-1个1~n的不重复数字,问1~n中那个数字没有出现

思路:vis标记的灵活运用

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<vector>
 4 #include<stack>
 5 #include<queue>
 6 #include<map>
 7 #include<set>
 8 #include<cstdio>
 9 #include<cstring>
10 #include<cmath>
11 #include<ctime>
12 #define fuck(x) cout<<#x<<" = "<<x<<endl;
13 #define ls (t<<1)
14 #define rs ((t<<1)+1)
15 using namespace std;
16 typedef long long ll;
17 typedef unsigned long long ull;
18 const int maxn = 100086;
19 const int inf = 2.1e9;
20 const ll Inf = 999999999999999999;
21 const int mod = 1000000007;
22 const double eps = 1e-6;
23 const double pi = acos(-1);
24 bool vis[15];
25 int main()
26 {
27     int T;
28     scanf("%d",&T);
29     while(T--){
30         int n,x;
31         memset(vis,0,sizeof(vis));
32         scanf("%d",&n);
33         for(int i=1;i<n;i++){
34             scanf("%d",&x);vis[x]=true;
35         }
36 
37         for(int i=1;i<=n;i++){
38             if(!vis[i]){printf("%d
",i);}
39         }
40     }
41     return 0;
42 }
View Code

 

Gym - 101915G Robots

题意:有一颗树,数的每条边都有一个权值,规定1号节点位根节点。有一堆机器人,也有各自的权值。机器人从根节点出发,只走比自己权值小的那个权值最大的边。求所有机器人停下来的节点的标号之和。

思路:DFS,先走权值大的边,在回溯之前,判断那些机器人会在当前节点停下来,具体方法是将机器人存在一个优先队列里面,在判断时,将>=走下来路上的最大的边的机器人留下来。如果一个机器人的值小于这个值,那么它走不到这里,而且走的顺序是按边由大到小,机器人走到了这里,说明它不能走到除了此处子节点以外的其他地方。而在回溯时,这个节点的子节点已经被判断完了,机器人还留在这里,说明它走不下去。由此可知,我们的策略应该是正确的

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<vector>
 4 #include<stack>
 5 #include<queue>
 6 #include<map>
 7 #include<set>
 8 #include<cstdio>
 9 #include<cstring>
10 #include<cmath>
11 #include<ctime>
12 #define fuck(x) cout<<#x<<" = "<<x<<endl;
13 #define ls (t<<1)
14 #define rs ((t<<1)+1)
15 using namespace std;
16 typedef long long ll;
17 typedef unsigned long long ull;
18 const int maxn = 100086;
19 const int inf = 2.1e9;
20 const ll Inf = 999999999999999999;
21 const int mod = 1000000007;
22 const double eps = 1e-6;
23 const double pi = acos(-1);
24 int n,m;
25 struct node
26 {
27     int v,w;
28 };
29 vector<node>u[maxn];
30 bool cmp(node a,node b)
31 {
32     return a.w>b.w;
33 }
34 bool vis[maxn];
35 ll ans;
36 priority_queue<int>q;
37 void dfs(int t,int f)
38 {
39     int siz =u[t].size();
40     vis[t]=true;
41     for(int i=0;i<siz;i++){
42         if(!vis[u[t][i].v]){
43             dfs(u[t][i].v,max(f,u[t][i].w));
44         }
45     }
46     vis[t]=false;
47     while(!q.empty()&&f<q.top()){
48         q.pop();
49         ans+=t;
50     }
51 }
52 
53 int main()
54 {
55     int T;
56     scanf("%d",&T);
57     while(T--){
58         scanf("%d%d",&n,&m);
59         for(int i=1;i<=n;i++){
60             u[i].clear();
61         }
62         int x,y,z;
63         for(int i=1;i<n;i++){
64             scanf("%d%d%d",&x,&y,&z);
65             u[x].push_back(node{y,z});
66             u[y].push_back(node{x,z});
67         }
68         for(int i=1;i<=m;i++){
69             int x;
70             scanf("%d",&x);
71             q.push(x);
72         }
73 
74         for(int i=1;i<=n;i++){
75             sort(u[i].begin(),u[i].end(),cmp);
76         }
77         ans = 0;
78         dfs(1,0);
79         printf("%lld
",ans);
80     }
81     return 0;
82 }
View Code

 

Gym - 101915H Buying Products

题意:妻管严被老婆赶出去买东西,每个商店有3个商品,但是他只能买两个,一共要买m个商品,问最小花费。

思路:取每家商店的最便宜的两件商品,放在一起,买下最便宜的m个

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<vector>
 4 #include<stack>
 5 #include<queue>
 6 #include<map>
 7 #include<set>
 8 #include<cstdio>
 9 #include<cstring>
10 #include<cmath>
11 #include<ctime>
12 #define fuck(x) cout<<#x<<" = "<<x<<endl;
13 #define ls (t<<1)
14 #define rs ((t<<1)+1)
15 using namespace std;
16 typedef long long ll;
17 typedef unsigned long long ull;
18 const int maxn = 100086;
19 const int inf = 2.1e9;
20 const ll Inf = 999999999999999999;
21 const int mod = 1000000007;
22 const double eps = 1e-6;
23 const double pi = acos(-1);
24 
25 int num[maxn];
26 int main()
27 {
28     int T;
29     scanf("%d",&T);
30     while(T--){
31         int n,k;
32         scanf("%d%d",&n,&k);
33         int s[5],t=0;
34         for(int i=1;i<=n;i++){
35             scanf("%d%d%d",&s[0],&s[1],&s[2]);
36             sort(s,s+3);
37             num[++t]=s[0];num[++t]=s[1];
38         }
39         sort(num+1,num+1+t);
40         int ans = 0;
41         for(int i=1;i<=k;i++){
42             ans+=num[i];
43         }
44         printf("%d
",ans);
45     }
46 
47     return 0;
48 }
View Code

 

Gym - 101915I A Movie in Byteland

题意:有很多字符串,你可以将他们随便排列,但是前面的字符串正着看和反着看都要分别比后面的任何一个字符串的字典序要小,而且任何相邻的两个字符串要满足一个有字母m,一个没有。求给定的字符串中最大可以排出多大满足条件的序列。

思路:先正着排一次序,记下序号id。反着排一次序,按次序将id加入树状数组中。已经在树状数组中的数据,一定是第二次排序的序号小于当前字符串的,树状数组中,小于id的数据,就是第一次排序的序号小于当前字符串的。建立两个树状数组,便可以分别维护,以含有m的字符串结尾的字符串序列的最大值和以不含m的字符串结尾的字符串序列的最大值。

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<vector>
 4 #include<stack>
 5 #include<queue>
 6 #include<map>
 7 #include<set>
 8 #include<cstdio>
 9 #include<cstring>
10 #include<cmath>
11 #include<ctime>
12 #define fuck(x) cout<<#x<<" = "<<x<<endl;
13 #define ls (t<<1)
14 #define rs ((t<<1)+1)
15 using namespace std;
16 typedef long long ll;
17 typedef unsigned long long ull;
18 const int maxn = 100005;
19 const int inf = 2.1e9;
20 const ll Inf = 999999999999999999;
21 const int mod = 1000000007;
22 const double eps = 1e-6;
23 const double pi = acos(-1);
24 int a[2][maxn];
25 struct node
26 {
27     string s,t;
28     int m,id;
29 }ss[maxn];
30 int n;
31 
32 int lowbit(int x)
33 {
34     return x&(-x);
35 }
36 
37 int query(int m,int x){
38     int ans=0;
39     while(x){
40         ans = max(ans,a[m][x]);
41         x-=lowbit(x);
42     }
43     return ans;
44 }
45 
46 void add(int m,int x,int num)
47 {
48     while(x<=n){
49         a[m][x]=max(a[m][x],num);
50         x+=lowbit(x);
51     }
52 }
53 
54 bool cmp(node a,node b)
55 {
56     return a.s<b.s;
57 }
58 
59 bool jud(node a,node b)
60 {
61     return a.t<b.t;
62 }
63 
64 int main()
65 {
66     int T;
67     cin>>T;
68     while(T--){
69         memset(a,0,sizeof(a));
70         cin>>n;
71         for(int i=1;i<=n;i++){
72             cin>>ss[i].s;
73             int siz = ss[i].s.size();
74             ss[i].t = ss[i].s;
75             ss[i].m = 0;
76             for(int j=0;j<siz;j++){
77                 if(ss[i].s[j]=='m'){ss[i].m=1;break;}
78             }
79             reverse(ss[i].t.begin(),ss[i].t.end());
80         }
81         sort(ss+1,ss+1+n,cmp);
82         for(int i=1;i<=n;i++){
83             ss[i].id=i;
84         }
85         sort(ss+1,ss+1+n,jud);
86         int ans = 0;
87 
88         for(int i=1;i<=n;i++){
89             int tmp;
90             tmp = query(ss[i].m^1,ss[i].id)+1;
91             ans = max(tmp,ans);
92             add(ss[i].m,ss[i].id,tmp);
93         }
94         cout<<ans<<endl;
95     }
96     return 0;
97 }
View Code

 

Gym - 101915J The Volcano Eruption

题意:有一个n*m的矩形框,你要从矩形顶走到矩形底,你想怎么走就怎么走,问最少通过多少区域。区域由圆形组成,两圆相交或相切视为同一区域。

思路:用并查集将圆合并,判断每一个并查集的左右边界,如果左右都超出了矩形框范围,那么答案++;

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<vector>
 4 #include<stack>
 5 #include<queue>
 6 #include<map>
 7 #include<set>
 8 #include<cstdio>
 9 #include<cstring>
10 #include<cmath>
11 #include<ctime>
12 #define ls (t<<1)
13 #define fuck(x) cout<<#x<<" = "<<x<<endl;
14 #define rs ((t<<1)+1)
15 using namespace std;
16 typedef long long ll;
17 typedef unsigned long long ull;
18 const int maxn = 1024;
19 const int inf = 2.1e9;
20 const ll Inf = 999999999999999999;
21 const int mod = 1000000007;
22 const double eps = 1e-6;
23 const double pi = acos(-1);
24 
25 int f[maxn];
26 ll x[maxn],y[maxn],r[maxn];
27 int n;ll w,l;
28 ll L[maxn],R[maxn];
29 
30 int getf(int x)
31 {
32     if(f[x]==x){return x;}
33     return f[x]=getf(f[x]);
34 }
35 
36 void Merge(int i,int j)
37 {
38     ll d1,d2;
39     ll x1,x2,y1,y2;
40     x1=x[i],y1=y[i],x2=x[j],y2=y[j];
41     d1=1ll*(x1-x2)*(x1-x2)+1ll*(y1-y2)*(y1-y2);
42     d2=(1ll*r[i]+1ll*r[j])*(1ll*r[i]+1ll*r[j]);
43     if(d1>d2){return;}
44     int t1 = getf(i);
45     int t2 = getf(j);
46     f[t2]=t1;
47 }
48 
49 int main()
50 {
51     int T;
52     scanf("%d",&T);
53     while(T--){
54         scanf("%d%lld%lld",&n,&w,&l);
55         for(int i=1;i<=n;i++){
56              scanf("%lld%lld%lld",&x[i],&y[i],&r[i]);
57              f[i]=i;
58              L[i]=Inf;R[i]=-1;
59         }
60         for(int i=1;i<=n;i++){
61             for(int j=i+1;j<=n;j++){
62                 Merge(i,j);
63             }
64         }
65         for(int i=1;i<=n;i++){
66             int s=getf(i);
67             L[s]=min(L[s],x[i]-r[i]);
68             R[s]=max(R[s],x[i]+r[i]);
69         }
70         int ans =0;
71         for(int i=1;i<=n;i++){
72             if(L[i]<=0&&R[i]>=w&&y[i]>=0&&y[i]<=l){ans++;}
73         }
74         printf("%d
",ans);
75     }
76     return 0;
77 }
View Code

Gym - 101915K Poor Ramzi

题意:有一个01串,将其分成1若干份,每一份的值就是1的个数,以这个值组成一个新串,问新串的为回文串的划分方案数。

思路:DFS,由外向内搜索,逐步深入即可。

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<vector>
 4 #include<stack>
 5 #include<queue>
 6 #include<map>
 7 #include<set>
 8 #include<cstdio>
 9 #include<cstring>
10 #include<cmath>
11 #include<ctime>
12 #define fuck(x) cout<<#x<<" = "<<x<<endl;
13 #define ls (t<<1)
14 #define rs ((t<<1)+1)
15 using namespace std;
16 typedef long long ll;
17 typedef unsigned long long ull;
18 const int maxn = 56;
19 const int inf = 2.1e9;
20 const ll Inf = 999999999999999999;
21 const int mod = 1000000007;
22 const double eps = 1e-6;
23 const double pi = acos(-1);
24 char s[maxn];
25 int dp[maxn][maxn];
26 ll dfs(int l,int r)
27 {
28     if(l>=r){return 1ll;}
29     if(dp[l][r]!=-1){return dp[l][r];}
30     ll ans =0;
31     int lsum = 0,rsum = 0;
32     for(int i=l;i<=r;i++){
33         lsum+=s[i]-'0';
34         rsum =0;
35         for(int j=r;j>i;j--){
36             rsum+=s[j]-'0';
37             if(rsum ==lsum){
38                 ans+=dfs(i+1,j-1);
39                 ans%=mod;
40             }
41         }
42     }
43     ans++;
44     return dp[l][r]=(ans%=mod);
45 }
46 
47 int main()
48 {
49     int T;
50     scanf("%d",&T);
51     while(T--){
52         scanf("%s",s);
53         memset(dp,-1,sizeof(dp));
54         int len = strlen(s);
55         printf("%lld
",dfs(0,len-1));
56     }
57     return 0;
58 }
View Code

Gym-101915L Eyb0ss

题意:就是求题目的那个公式

思路:这个题目似曾相识,可是就是不知道怎么写,题解又搜不到,好气呀。

原文地址:https://www.cnblogs.com/ZGQblogs/p/10136243.html