1. 程式人生 > >The 2018 ACM-ICPC Asia Qingdao Regional Contest, Online - H Traveling on the Axis-【思維模擬題目】

The 2018 ACM-ICPC Asia Qingdao Regional Contest, Online - H Traveling on the Axis-【思維模擬題目】

view 本地 lang char following ring listitem swe src

H Traveling on the Axis   

作者: 浙江大學競賽命題組 單位: ACMICPC 時間限制: 500 ms 內存限制: 64 MB 代碼長度限制: 32 KB 傳送門

BaoBao is taking a walk in the interval [0,n] on the number axis, but he is not free to move, as at every point (i0.5) for all i[1,n], where i is an integer, stands a traffic light of type t?i?? (t?i??{0,1}).

BaoBao decides to begin his walk from point p and end his walk at point q (both pand q are integers, and p<q). During each unit of time, the following events will happen in order:

  1. Let‘s say BaoBao is currently at point x, he will then check the traffic light at point (x+0.5). If the traffic light is green, BaoBao will move to point (x+1); If the traffic light is red, BaoBao will remain at point x.
  2. All the traffic lights change their colors. If a traffic light is currently red, it will change to green; If a traffic light is currently green, it will change to red.

A traffic light of type 0 is initially red, and a traffic light of type 1 is initially green.

Denote t(p,q) as the total units of time BaoBao needs to move from point p to point q. For some reason, BaoBao wants you to help him calculate

技術分享圖片

where both p and q are integers. Can you help him?

Input

There are multiple test cases. The first line of the input contains an integer T, indicating the number of test cases. For each test case:

The first and only line contains a string s (1s10?^5??, s=n, s?i??{‘0’,‘1’} for all 1is∣), indicating the types of the traffic lights. If s?i??=‘0’, the traffic light at point (i0.5) is of type 0 and is initially red; If s?i??=‘1’, the traffic light at point (i0.5) is of type 1 and is initially green.

It‘s guaranteed that the sum of s∣ of all test cases will not exceed 10?6??.

Output

For each test case output one line containing one integer, indicating the answer.

Sample Input
3
101
011
11010
Sample Output
12
15
43
Hint

For the first sample test case, it‘s easy to calculate that t(0,1)=1, t(0,2)=2, t(0,3)=3, t(1,2)=2, t(1,3)=3 and t(2,3)=1, so the answer is 1+2+3+2+3+1=12.

For the second sample test case, it‘s easy to calculate that t(0,1)=2, t(0,2)=3, t(0,3)=5, t(1,2)=1, t(1,3)=3 and t(2,3)=1, so the answer is 2+3+5+1+3+1=15.


題目思路:

  1. 題目解釋的樣例,見樣例
  2. 題目做的時候,起初用的三重循環,10^5d的單重循環量,三重循環枚舉每種情況的每個起點和終點——直接炸了!想了想,可以進行優化!優化時,可以計算當前區間在作為起點的過程中,其實可以被計算len-k次,這樣復雜度直接降為了10^10,心裏捉摸了一下跑了一個裸的兩重循環——在本地也炸了!闊怕!
  3. len表示本題的數字串長度!
  4. 左想右想,發現一重循環才是正解!瞎猜了一陣子無果!發現每次跑循環計算第k(k從0到len-1)個區間的時候,可以一次性把全部計算出來!即當前區間遍歷的次數等於把該區間當做第一個起點的情況個數(len-k)個,再加上之前的區間的為起點並且覆蓋到第k個區間的個數(設為num),num怎麽求呢!
  5. num仔細根據樣例推推發現,每輪走到的行數都是該列數字所對應的行數“1”上,然後從該列行數作為起點的也必須是從“1”出發的!這會有簡單的回合!開一個f1和f2分別進行記錄!
  6. 其余的見代碼的註釋吧!手推樣例還是很重要的!

真數據:

真測試輸入
4
10100101010101010101010101011110101010101
111111111111111110100101010101010101010101011110101010101
1111111111111111111
00000000000000000000000000

真測試輸出

13951
41543
2470
6552

感興趣的可以試試上面的數據,應該沒問題!

代碼;

技術分享圖片
#include<stdio.h>
#include<iostream>
#include<cmath>
#include<string>
#include<string.h>
#include<time.h>
#include<algorithm>
using namespace std;
const double eps=1e-7;
#define PI acos(-1.0)
#define ll long long
#define mian main
#define mem(a,b) memset(a,b,sizeof(a))


char a[100005];
int b[100005][2];
int main()
{

    int T;
    while(scanf("%d",&T)!=EOF)
    {
        while(T--)
        {
            scanf("%s",a);
            int len=strlen(a);
            for(int i=0; i<len; i++)
            {
                b[i][0]=a[i]-0;  ///原數據層
                b[i][1]=!b[i][0];  ///紅綠燈交替一遍後!若紅綠燈再交替一遍其實就是上一層!
            }

            int Time=0;
            int  ans=0,k=0;
            int f1=0,f2=-1;//表示當前層數0或者1

            int num1=0,num2=0;
            for(int k=0; k<len; k++)  ///暴力枚舉一遍len個區間即可!!
            {
                if(f1==f2)
                {
                    f2=-1;
                    num1+=num2;
                    num2=0;
                }
                num1-=k;  ///這裏是個終點,每往後走一個,會少k個前面的區間覆蓋到當前區間的,必須減去
             //   printf(" (f1=%d f2=%d) ",f1,f2);
                if(f1==0) ///分配每輪的萌新層,與f1層相符就加進f1裏
                {
                    num1+=len-k;
                }
                else     ///否則就新開一個f2來進行記錄!
                {
                    if(f2==-1)
                        f2=0;
                    num2+=len-k;
                }

                if(b[k][f1]==1)
                {
                    ans+=1*(num1 ),f1=!f1;
                }
                else
                    ans+=2*(num1 );
                if(f2!=-1)
                {
                    if(b[k][f2]==1)
                    {
                        ans+=1*(num2 ),f2=!f2;
                    }
                    else
                        ans+=2*(num2 );
                }

                //   printf("&%d ",ans);
                //    printf("endd =%d ans_sum=%d\n",j,ans);
                //    printf("]%d\n",ans);
           //     printf("--> (f1=%d f2=%d)\n",f1,f2);
            //    printf("num1=%d num2=%d Time=%d &ans=%d\n",num1,num2,++Time,ans);
            }
            printf("%d\n",ans);
        }

    }

    return 0;
}
View Code(有大量註釋)

The 2018 ACM-ICPC Asia Qingdao Regional Contest, Online - H Traveling on the Axis-【思維模擬題目】