2016大连网络赛

1010 Weak Pair

题解:树状数组/线段树 +离散化+dfs 对于每个a[i],将k/a[i]也放进去离散,这样的话对于每个数就能知道k/a[i]之前的有多少个数,从根节点开始dfs,然后找向它的子节点,看能不能匹配,而会造成影响的只有兄弟节点,那么在每次访问完一个节点的子节点之后删除这个点的贡献

线段树版本:

  1 #include <iostream>
  2 #include <stdio.h>
  3 #include <string.h>
  4 #include <algorithm>
  5 #include <stdlib.h>
  6 #include <vector>
  7 #include <queue>
  8 #include <stack>
  9 #include <string>
 10 using namespace std;
 11 const int maxn=3*1e5+10;
 12 #define MS(a,b) memset(a,b,sizeof(a))
 13 long long a[maxn];
 14 long long b[maxn];
 15 long long k;
 16 int n,m;
 17 vector<int> G[maxn];
 18 int in[maxn];
 19 long long ans;
 20 struct node
 21 {
 22     int l,r;
 23     int mid(){return (l+r)>>1;}
 24     long long sum;
 25 };
 26 node tree[maxn<<2];
 27 void pushup(int rt)
 28 {
 29     tree[rt].sum=tree[rt<<1].sum+tree[rt<<1|1].sum;
 30 }
 31 void build(int l,int r,int rt)
 32 {
 33     tree[rt].l=l,tree[rt].r=r;
 34     tree[rt].sum=0;
 35     if(l==r) return ;
 36     int mid=tree[rt].mid();
 37     build(l,mid,rt<<1);
 38     build(mid+1,r,rt<<1|1);
 39 }
 40 void update(int index,int x,int L,int R,int rt)
 41 {
 42     if(L==index&&R==index)
 43     {
 44         tree[rt].sum+=x;
 45         return ;
 46     }
 47     int mid=tree[rt].mid();
 48     if(index<=mid) update(index,x,L,mid,rt<<1);
 49     else if(index>mid) update(index,x,mid+1,R,rt<<1|1);
 50     pushup(rt);
 51 }
 52 long long query(int l,int r,int L,int R,int rt)
 53 {
 54     if(L>=l&&R<=r) return tree[rt].sum;
 55     int mid=tree[rt].mid();
 56     long long ans=0;
 57     if(l<=mid) ans+=query(l,r,L,mid,rt<<1);
 58     if(r>mid) ans+=query(l,r,mid+1,R,rt<<1|1);
 59     return ans;
 60 }
 61 void dfs(int x)
 62 {
 63     int l=lower_bound(b+1,b+1+m,k/a[x])-b;
 64     int pos=lower_bound(b+1,b+1+m,a[x])-b;
 65     ans+=query(1,l,1,m,1);
 66     update(pos,1,1,m,1);
 67     for(int i=0;i<G[x].size();i++) dfs(G[x][i]);
 68     update(pos,-1,1,m,1);
 69 }
 70 void init()
 71 {
 72     for(int i=0;i<=n+1;i++) G[i].clear();
 73     build(1,m,1);
 74     MS(in,0);
 75     ans=0;
 76 }
 77 int main()
 78 {
 79     int T;
 80     scanf("%d",&T);
 81     while(T--)
 82     {
 83         //init();
 84         scanf("%d %lld",&n,&k);
 85         int cnt=1;
 86         for(int i=1;i<=n;i++)scanf("%lld",&a[i]);
 87             for(int i=1;i<=n;i++)
 88             {
 89                 b[cnt]=a[i];
 90                 cnt++;
 91                 b[cnt]=k/a[i];
 92                 cnt++;
 93             }
 94         m=cnt-1;
 95         sort(b+1,b+1+m);
 96         init();
 97         for(int i=1;i<=n-1;i++)
 98         {
 99             int x,y;
100             scanf("%d %d",&x,&y);
101             G[x].push_back(y);
102             in[y]++;
103         }
104         int root;
105         for(int i=1;i<=n;i++)
106         {
107             if(in[i]==0)
108             {
109                 root=i;
110                 break;
111             }
112         }
113         dfs(root);
114         printf("%lld
",ans);
115 
116     }
117     return 0;
118 }
View Code

  树状数组版本:

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <stdlib.h>
#include <vector>
#include <queue>
#include <stack>
#include <string>
using namespace std;
const int maxn=3*1e5+10;
#define MS(a,b) memset(a,b,sizeof(a))
long long a[maxn];
long long b[maxn];
long long k;
int n,m;
vector<int> G[maxn];
int in[maxn];
long long ans;
long long tree[maxn];
void add(int pos,int x)
{
    while(pos<=2*m)
    {
        tree[pos]+=x;
        pos+=(pos&(-pos));
    }
}
long long query(int pos)
{
    long long sum=0;
    while(pos>0)
    {
        sum+=tree[pos];
        pos-=(pos&(-pos));
    }
    return sum;
}
void dfs(int x)
{
    int l=lower_bound(b+1,b+1+m,k/a[x])-b;
    int pos=lower_bound(b+1,b+1+m,a[x])-b;
    ans+=query(l);
    add(pos,1);
    for(int i=0;i<G[x].size();i++) dfs(G[x][i]);
    add(pos,-1);
}
void init()
{
    for(int i=0;i<=n+1;i++) G[i].clear();
    MS(tree,0);
    MS(in,0);
    ans=0;
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        init();
        scanf("%d %lld",&n,&k);
        int cnt=1;
        for(int i=1;i<=n;i++)scanf("%lld",&a[i]);
            for(int i=1;i<=n;i++)
            {
                b[cnt]=a[i];
                cnt++;
                b[cnt]=k/a[i];
                cnt++;
            }
        m=cnt-1;
        sort(b+1,b+1+m);
        for(int i=1;i<=n-1;i++)
        {
            int x,y;
            scanf("%d %d",&x,&y);
            G[x].push_back(y);
            in[y]++;
        }
        int root;
        for(int i=1;i<=n;i++)
        {
            if(in[i]==0)
            {
                root=i;
                break;
            }
        }
        dfs(root);
        printf("%lld
",ans);

    }
    return 0;
}
View Code

1009 Sparse Graph

题解:就是求一个补图的最短路,考虑到实际上补图每条边的权值时一样的,那么可以使用bfs求一个最短路,用set保存访问过的点和没访问过的点,因为点如果访问过了,那么肯定肯定是最短的,再从已经访问到的点开始扩展,做完这题可以看看scu4444和这题的思路基本一样

 1 #include <iostream>
 2 #include <algorithm>
 3 #include <queue>
 4 #include <set>
 5 #include <stdio.h>
 6 #include <string.h>
 7 #include <stdlib.h>
 8 #include <map>
 9 #include <vector>
10 #include <math.h>
11 using namespace std;
12 const int maxn=200*1000+10;
13 int n,m;
14 set<int> novis;
15 set<int> vis;
16 vector<int> G[maxn];
17 int dis[maxn];
18 void bfs(int s)
19 {
20     memset(dis,-1,sizeof(dis));
21     queue<int> q;
22     q.push(s);
23     dis[s]=0;
24     while(!q.empty()&&novis.size())
25     {
26         int x=q.front();
27         q.pop();
28         for(int i=0;i<G[x].size();i++)
29         {
30             if(!novis.count(G[x][i])) continue;
31             novis.erase(G[x][i]);
32             vis.insert(G[x][i]);
33         }
34         for(auto it:novis)
35         {
36             dis[it]=dis[x]+1;
37             q.push(it);
38         }
39         novis.swap(vis);
40         vis.clear();
41         
42     }
43 }
44 int main()
45 {
46     int T;
47     scanf("%d",&T);
48     while(T--)
49     {
50         vis.clear();
51         novis.clear();
52         scanf("%d %d",&n,&m);
53         for(int i=1;i<=n;i++) G[i].clear();
54         for(int i=1;i<=m;i++)
55         {
56             int x,y;
57             scanf("%d %d",&x,&y);
58             G[x].push_back(y);
59             G[y].push_back(x);
60         }
61         int s;
62         scanf("%d",&s);
63         for(int i=1;i<=n;i++)
64         {
65             if(i==s) continue;
66             novis.insert(i);
67         }
68         int cnt=1;
69         bfs(s);
70         for(int i=1;i<=n;i++)
71         {
72             if(i==s) continue;
73             cnt++;
74             printf("%d%c",dis[i],cnt==n?'
':' ');
75             
76         }
77         
78     }
79     return 0;
80 }
View Code

1008 Function

题解:如果a>=b,那么a%b<=a/2;

一个数n从本来的位置递减到0最多只需要logn次,也就是往右递减的位置最多不超过30个,那么我们就可以预处理出每个数往右递减的位置,然后离线询问,

用一个优先队列存储数和数所在的位置,比如8 7 6 9 10,先push(8,1)进去,然后每次把队首拿出来,8%7=1,把(1,1)push进去,然后把(8,1)pop出来,(7,2)push进去,优先队列最大值优先,当队首元素小于当前元素的时候,把当前元素和位置push进去,开始枚举下一个数

 1 #include <iostream>
 2 #include <algorithm>
 3 #include <stdio.h>
 4 #include <string.h>
 5 #include <stdlib.h>
 6 #include <queue>
 7 using namespace std;
 8 const int maxn=1e5+10;
 9 struct node
10 {
11     int id;
12     int data;
13     int cnt;
14     friend bool operator < (const node&a,const node&b)
15     {
16         return a.data<b.data;
17     }
18 };
19 struct node2
20 {
21     int pos;
22     int data;
23     void init()
24     {
25         pos=0;
26     }
27 };
28 node a[maxn];
29 node2 pos[maxn][32];
30 priority_queue<node> q;
31 int main()
32 {
33     int T;
34     scanf("%d",&T);
35     while(T--)
36     {
37         while(!q.empty()) q.pop();
38         int n;
39         scanf("%d",&n);
40         for(int i=1;i<=n;i++)
41         {
42             int x;
43             scanf("%d",&x);
44             a[i].data=x;
45             a[i].id=i;
46             a[i].cnt=0;
47             pos[i][0].data=x;
48             pos[i][0].pos=i;
49             for(int j=1;j<=30;j++)
50             {
51                 pos[i][j].init();
52             }
53         }
54         q.push(a[1]);
55         for(int i=2;i<=n;i++)
56         {
57             node tmp;
58             while(q.top().data>=a[i].data)
59             {
60                 tmp=q.top();
61                 q.pop();
62                 tmp.data%=a[i].data;
63                 tmp.cnt+=1;
64                 pos[tmp.id][tmp.cnt].pos=i;
65                 pos[tmp.id][tmp.cnt].data=tmp.data;
66                 q.push(tmp);
67                 
68             }
69             q.push(a[i]);
70         }
71         int m;
72         scanf("%d",&m);
73         while(m--)
74         {
75             int l,r;
76             int ans;
77             scanf("%d %d",&l,&r);
78             if(l==r){
79                 printf("%d
",a[l].data);
80                 continue;
81             }
82             else
83             {
84                 for(int i=0;i<=30;i++)
85                 {
86                     
87                     if(pos[l][i].pos>r||pos[l][i].pos==0) break;
88                     ans=pos[l][i].data;
89                 }
90                 printf("%d
",ans);
91             }
92         }
93         
94     }
95     return 0;
96 }
View Code

1006 Football Games

题解:迷幻的题目。。。

 1 #include <iostream>
 2 #include <stdio.h>
 3 #include <string.h>
 4 #include <stdlib.h>
 5 #include <algorithm>
 6 #include <vector>
 7 #include <map>
 8 #include <queue>
 9 using namespace std;
10 const int maxn=1e5;
11 int b[maxn];
12 int main()
13 {
14     int n,m;
15     while(scanf("%d",&m)!=EOF)
16     {
17         while(m--)
18         {
19             scanf("%d",&n);
20             int sum=0;
21             for(int i=1;i<=n;i++)
22             {
23                 scanf("%d",&b[i]);
24                 sum+=b[i];
25             }
26             bool flag=true;
27             int cnt1=0,cnt2=0;
28             for(int i=1;i<=n;i++)
29             {
30                 if(b[i]==0)
31                 {
32                     cnt1++;
33                     if(cnt1>1)
34                     {
35                         flag=false;
36                         break;
37                     }
38                 }
39                 if(b[i]==2*(n-1))
40                 {
41                     cnt2++;
42                     if(cnt2>1)
43                     {
44                         flag=false;
45                         break;
46                     }
47                 }
48                 if(b[i]>2*(n-1))
49                 {
50                     flag=false;
51                     break;
52                 }
53             }
54             if(sum!=n*(n-1)) flag=false;
55             if(flag) printf("T
");
56             else printf("F
");
57         }
58 
59     }
60     return 0;
61 }
View Code

 

原文地址:https://www.cnblogs.com/as3asddd/p/5861648.html