Voting CodeForces - 749C

有点意思的题

Voting CodeForces - 749C

题意:有n个人投票,每次按照第1个人~第n个人的顺序发言,如果到某个人发言时他已经被禁止发言就跳过,每个人发言时可以禁止另一个人发言或什么也不做。最后只剩下一个人时,那个人的意见就是最终决定的意见。这些人分为D和R两派,也就是每个人有D和R两种意见中的一种,每一派的人都希望自己派的意见成为最终意见。假设每个人都作出最优选择,请根据每个人的派别判断最终决定的意见。

方法:第i个人发言的时候,就按照第i~第n,第1~第i-1的顺序找出第一个出现的与自己不同派别且没有被禁言的人,将其禁言。当只剩下某一派时,显然这一派的意见就是最终意见。

方法虽然简单,但是实现起来会遇到很多困难。

垃圾程序(模拟)1

 1 #include<cstdio>
 2 int type[200100];
 3 int next1[200100];//next1[i]表示i之后第一个不同党的位置
 4 int first1[2];//first1[i]表示从前数起第一个i的位置
 5 int next2[200100];//next2[i]表示i之后第一个同党的位置
 6 int temp[2];
 7 bool nok[200100];
 8 int n,now;
 9 int main()
10 {
11     int i;
12     char c;
13     scanf("%d\n",&n);
14     for(i=1;i<=n;i++)
15     {
16         scanf("%c",&c);
17         if(c=='D')
18             type[i]=0;
19         else
20             type[i]=1;
21     }
22     for(i=n;i>=1;i--)
23     {
24         next1[i]=temp[type[i]^1];
25         temp[type[i]]=i;
26     }
27     for(i=n;i>=1;i--)
28     {
29         next2[i]=first1[type[i]];
30         first1[type[i]]=i;
31     }
32     now=n;
33     while(true)
34     {
35         for(i=1;i<=n;i++)
36         {
37             if(nok[i])    continue;
38             if(now==1)
39             {
40                 if(type[i]==0)
41                     printf("D");
42                 else
43                     printf("R");
44                 return 0;
45             }
46             while(nok[next1[i]]==true)    next1[i]=next2[next1[i]];
47             while(nok[first1[i]]==true)    first1[i]=next2[next1[i]];
48             if(next1[i])
49             {
50                 nok[next1[i]]=true;
51                 next1[i]=next2[next1[i]];
52             }
53             else if(first1[type[i]^1])
54             {
55                 nok[first1[type[i]^1]]=true;
56                 first1[type[i]^1]=next2[first1[type[i]^1]];
57             }
58             else
59             {
60                 if(type[i]==0)
61                     printf("D");
62                 else
63                     printf("R");
64                 return 0;
65             }
66         }
67     }
68     return 0;
69 }
View Code

垃圾程序(模拟)2

 1 #include<cstdio>
 2 int type[200100];
 3 int next1[200100];//next1[i]表示i之后第一个不同党的位置
 4 int first1[2];//first1[i]表示从前数起第一个i的位置
 5 int next2[200100];//next2[i]表示i之后第一个同党的位置
 6 int temp[2];
 7 bool nok[200100];
 8 int n,now;
 9 int main()
10 {
11     int i;
12     char c;
13     scanf("%d\n",&n);
14     for(i=1;i<=n;i++)
15     {
16         scanf("%c",&c);
17         if(c=='D')
18             type[i]=0;
19         else
20             type[i]=1;
21     }
22     for(i=n;i>=1;i--)
23     {
24         next1[i]=temp[type[i]^1];
25         temp[type[i]]=i;
26     }
27     for(i=n;i>=1;i--)
28     {
29         next2[i]=first1[type[i]];
30         first1[type[i]]=i;
31     }
32     now=n;
33     while(true)
34     {
35         for(i=1;i<=n;i++)
36         {
37             if(nok[i])    continue;
38             if(now==1)
39             {
40                 if(type[i]==0)
41                     printf("D");
42                 else
43                     printf("R");
44                 return 0;
45             }
46             while(nok[next1[i]]==true)    next1[i]=next2[next1[i]];
47             while(nok[first1[i]]==true)    first1[i]=next2[first1[i]];
48             if(next1[i])
49             {
50                 nok[next1[i]]=true;
51                 now--;
52                 next1[i]=next2[next1[i]];
53             }
54             else if(first1[type[i]^1])
55             {
56                 nok[first1[type[i]^1]]=true;
57                 now--;
58                 first1[type[i]^1]=next2[first1[type[i]^1]];
59             }
60             else
61             {
62                 if(type[i]==0)
63                     printf("D");
64                 else
65                     printf("R");
66                 return 0;
67             }
68         }
69     }
70     return 0;
71 }
View Code

后来看了题解,发现可以用三个队列按照(i~n,1~i-1)的顺序分别存储(所有的,与当前人同派的,与当前人异派的)且未被禁言的人的序号

然后,又炸了两次...所以要小心

 1 //第i个人按照先i到n,再1到i-1的顺序找出第一个不同派别的deny
 2 #include<cstdio>
 3 #include<queue>
 4 using namespace std;
 5 bool type[200100];
 6 bool deny[200100];
 7 queue<int> q[2],q2;
 8 int n;
 9 int main()
10 {
11     int i,now,now2;
12     char c;
13     scanf("%d\n",&n);
14     for(i=1;i<=n;i++)
15     {
16         scanf("%c",&c);
17         if(c=='R')
18             type[i]=1;
19         q[type[i]].push(i);
20         q2.push(i);
21     }
22     while(!q[0].empty()&&!q[1].empty())
23     {
24         now=q2.front();
25         q2.pop();
26         if(deny[now])    continue;
27         //此时now就为当前要发言的(未被禁言的)人
28         now2=q[type[now]^1].front();//now要禁言的人
29         q[type[now]^1].pop();//由于now2被禁言,就不放回队列了
30         deny[now2]=true;
31         q[type[now]].pop();//第二次交加上的,now已经发完言,从队列中退出
32         q[type[now]].push(now);//第三次交加上的,并放回到队列尾部 
33         q2.push(now);
34     }
35     if(q[0].empty())
36         printf("R");
37     else
38         printf("D");
39     return 0;
40 }
posted @ 2017-09-10 19:22  hehe_54321  阅读(244)  评论(0编辑  收藏  举报
AmazingCounters.com