【2013杭州区域赛】部分题解 hdu4770—4780

1008:

题意:

有20W个数,每个数都在20W以内,现在有20W个询问,每次询问L,R区间内不会打架的数有多少个

定义两个数不互质 就会打架

解法:

脑洞很大的一道题,先要进行预处理,对每一个数预处理出 最大的,没有跟他不互质数(即这个数不会打架)的区间

显然可以通过找到这个数左边和右边的第一个跟他互质的数来求得此区间,那么这个怎么求呢,发现可以通过枚举当前数的质因数找到

我们先处理,每一个数左边的最后一次出现的坐标,这样每扫到一个数,都只需要对这个数及其质因数进行更新

找到了每个数的上述区间后,我们发现设某个数的上述区间为 [L,R],这个数自己的位置为pos,现在对于一个询问[a,b]

这个数是询问中的一个答案的条件就是   L<=a,b<=R 且 a<=pos<=b。现在可以离线进行更新和查询

我们可以在L 处将区间[pos,R]位置的值+1,并在pos处对该区间的值 -1,那么对于某个查询[a,b] 只需要在扫到a的时候,单点查询b的值即可

代码:

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 int a[200020];
  4 int l[200020];
  5 int r[200020];
  6 int pre[200020];
  7 vector<int>d[200020];
  8 bool np[200020];
  9 void setprime(int maxn)
 10 {
 11     memset(np,0,sizeof(np));
 12     for(int i=2; i<=maxn; i++)
 13     {
 14         if(np[i]==0)
 15             d[i].push_back(i);
 16         for(int j=i+i; j<=maxn; j+=i)
 17         {
 18             np[j]=1;
 19             if(np[i]==0)
 20                 d[j].push_back(i);
 21         }
 22     }
 23 }
 24 int n,m;
 25 struct node
 26 {
 27     int type; //-1:+1 -2:-1,else &sup2;é&Ntilde;&macr;;
 28     int pos;
 29     int num;
 30     bool operator <(const node a)const
 31     {
 32         if(pos!=a.pos)
 33             return pos<a.pos;
 34         else
 35         {
 36             return type<a.type;
 37         }
 38     }
 39 };
 40 int ans[200020];
 41 vector<node>q;
 42 int t[200020];
 43 int lowbit(int x)
 44 {
 45     return x&(-x);
 46 }
 47 
 48 int getSum(int x)
 49 {
 50     int sum = 0;
 51     while(x)
 52     {
 53         sum += t[x];
 54         x -= lowbit(x);
 55     }
 56     return sum;
 57 }
 58 
 59 void add(int x , int val)
 60 {
 61     while(x <=200010)
 62     {
 63         t[x] += val;
 64         x += lowbit(x);
 65     }
 66 }
 67 void init()
 68 {
 69     memset(t,0,sizeof(t));
 70     q.clear();
 71     memset(l,0,sizeof(l));
 72     for(int i=1; i<=n; i++)
 73     {
 74         r[i]=n+1;
 75     }
 76 }
 77 int main()
 78 {
 79     //freopen("in.txt","r",stdin);
 80     setprime(200000);
 81     while(scanf("%d%d",&n,&m),n+m)
 82     {
 83         init();
 84         for(int i=1; i<=n; i++)
 85         {
 86             scanf("%d",a+i);
 87         }
 88         memset(pre,0,sizeof(pre));
 89         for(int i=1; i<=n; i++)
 90         {
 91             for(int j=0; j<(int)d[a[i]].size(); j++)
 92             {
 93                 int now=d[a[i]][j];
 94                 l[i]=max(pre[now],l[i]);
 95                 pre[now]=i;
 96             }
 97             l[i]++;
 98         }
 99         memset(pre,0x3f,sizeof(pre));
100         for(int i=n; i>0; i--)
101         {
102             for(int j=0; j<(int)d[a[i]].size(); j++)
103             {
104                 int now=d[a[i]][j];
105                 r[i]=min(pre[now],r[i]);
106                 pre[now]=i;
107             }
108             r[i]--;
109             q.push_back(node {-1,l[i],i});
110             q.push_back(node {m,i,i});
111         }
112         for(int i=0; i<m; i++)
113         {
114             int u,v;
115             scanf("%d%d",&u,&v);
116             q.push_back(node {i,u,v});
117         }
118         //printf("%d\n",q.size());
119         sort(q.begin(),q.end());
120         for(int i=0; i<(int)q.size(); i++)
121         {
122             node now=q[i];
123             if(now.type==-1)
124             {
125                 add(now.num,1);
126                 add(r[now.num]+1,-1);
127             }
128             if(now.type==m)
129             {
130                 add(now.num,-1);
131                 add(r[now.num]+1,1);
132             }
133             if(now.type>=0&&now.type<m)
134             {
135                 ans[now.type]=getSum(now.num);
136             }
137         }
138         for(int i=0; i<m; i++)
139         {
140             printf("%d\n",ans[i]);
141         }
142     }
143     return 0;
144 }
View Code

 

1009:

题意:

有g种不同颜色的小球,b个袋子,每个袋子里面有若干个每种小球

两人轮流取袋子,当袋子里面的同色小球有s个时,会合并成一个魔法球,并被此次取袋子的人获得

成功获得魔法球的人可以再次取

求二者都进行最优策略之后两人所得魔法球个数差

解法:

数据不大,考虑搜索,发现不行,于是可以记忆化搜索,转移不难想到

代码:

 1 #include <iostream>
 2 #include <stdio.h>
 3 #include<string.h>
 4 #include<algorithm>
 5 #include<string>
 6 #include<ctype.h>
 7 using namespace std;
 8 #define MAXN 10000
 9 typedef struct Node
10 {
11     int a,b;
12 }node;
13 node dp[2097152];
14 bool vi[2097152];
15 int num[25][25];
16 int p[8];
17 int g,b,s,k,m,x;
18 void dfs(int state,int turn)
19 {
20     if(state==(1<<b)-1)
21     {
22         dp[state].a=0;
23         dp[state].b=0;
24         return ;
25     }
26     if(vi[state])
27     {
28         return ;
29     }
30     int ok;
31     node t;
32     node ans;
33     ans.a=-1000000;
34     ans.b=0;
35     int pp[8];
36     memcpy(pp,p,sizeof(pp));
37     for(int i=0;i<b;i++)
38     {
39         t.a=0;
40         t.b=0;
41         ok=0;
42         if(state&(1<<i))
43           continue;
44         int st=state|(1<<i); //状态
45         for(int j=0;j<g;j++)
46         {
47             p[j]+=num[i][j];
48             ok+=p[j]/s;
49             p[j]%=s;
50         }
51         int tur=ok?turn:!turn;//是否交换选手
52         dfs(st,tur);
53         memcpy(p,pp,sizeof(pp));
54         t.a+=ok;
55         if(tur==turn)   //子状态的先手所要转移到的状态相同
56         {
57             t.a+=dp[st].a;
58             t.b+=dp[st].b;
59         }
60         else            //选手交换了
61         {
62             t.b+=dp[st].a;
63             t.a+=dp[st].b;
64         }
65         if(t.a-t.b>ans.a-ans.b)
66         {
67             ans=t;
68         }
69     }
70     vi[state]=1;
71     dp[state]=ans;
72     return ;
73 }
74 int main()
75 {
76     while(scanf("%d%d%d",&g,&b,&s),g+b+s)
77     {
78         memset(num,0,sizeof(num));
79         for(int i=0;i<b;i++)
80         {
81             scanf("%d",&k);
82             while(k--)
83             {
84                 scanf("%d",&x);
85                 num[i][x-1]++;
86             }
87         }
88         memset(p,0,sizeof(p));
89         memset(vi,0,sizeof(vi));
90         dfs(0,0);
91         printf("%d\n",dp[0].a-dp[0].b);
92     }
93     return 0;
94 }
View Code

 

posted @ 2015-09-02 14:58  PlasticSpirit  阅读(562)  评论(3编辑  收藏  举报