10月集訓test3

所以不知道爲什麼test1和test2再次一起消失了。。。。
可能或許大概有時間會補上吧。
呵呵。
上題(那什麼,最近降溫好厲害。。好。。冷。。啊。。)

1.短文評估

爲了維持生計,上學期期末迎考期間小可可在育紅小學兼任了英語助教。首要任務就是協助英語教研室的老師們挑選合適的短文作爲寒假作業佈置給小朋友們,以提高他們的英語閱讀能力。
挑選短文有一個評價標準。那就是同樣長的文章,出現的單詞越少越好,也就是說文章中詞彙出現的頻度越高越好。小可可根據思路設計了一個評估函數:
這裏寫圖片描述

這個函數值越大,文章閱讀難度越小。其中:T 是待評估的短文;Q(T)是短文中的單詞數量,相同的單詞重複計算;ψ(T)是短文 T 中單詞構成的集合,單詞是不區分大小寫的,且該集合中沒有重複的元素;f(w,T) 表示單詞 w 在短文 T 中出現的次數。這裏寫圖片描述表示短文 T 中出現的各個不同單詞的出現次數的四次方和。
爲了簡化處理,同一個英語單詞的不同形態(如複數、過去式、過去分詞等)算作不同單詞。除了英文字母,短文中出現的數字和標點符號都不算單詞,只能算作分隔符。

例如短文:The International Olympic Committee (IOC) will decide the 2012 Olympic Games host in three years at a meeting in Singapore.

這篇短文的Q(T)=19。 是由 The,International,Olympic,Committee,IOC,will,decide,Games,host,in,three,years,at,a,meeting,Singapore等單詞構成的集合(注意:The 和 the算同一個單詞),這些單詞在該短文中出現的次數分別是 2,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1。
因此:
這裏寫圖片描述

所以該短文的評估值
這裏寫圖片描述

計算短文的評估值可不是一件輕鬆的事情,爲了提高小可可的工作效率,請你幫她編寫一個程序,只需要求出計算短文評估值所需要的 P(T) 和 Q(T) 。

輸入格式

輸入文件中所有的內容構成了待評估短文 T ,並且已知待評估短文的 Q(T)≤1000,任何一個單詞的長度不超過 40 個字符,出現的次數不超過 50 。文章可能有很多段,段與段之間可能有一行空行,也可能沒有。沒有單詞被拆分長兩段。

輸出格式

在一行輸出兩個整數,分別代表 P(T) 和 Q(T) 。兩個整數之間用一個空格隔開。

樣例數據1

輸入
The International Olympic Committee (IOC) will decide the 2012 Olympic Games host in three years at a meeting in Singapore.

輸出
61 19

樣例數據 2

輸入
The International Olympic Committee (IOC) will decide the 2012 Olympic Games host in three years at a meeting in Singa23pore.

輸出
62 20

其實真的是模擬啊啊啊啊啊(畫圈圈)。
但是,單詞的定義真的是從輸入就開始錯。。果然還是一個一個字符的輸入比較好,等到輸入的什麼字符也不是,break。
先算出Q(T),再將大寫字母改爲小寫字母,然後先算出每個數的個數,算出不同個數出現的次數,最後計算P(T)。
吶,代碼。

#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<string>
#include<ctime>
#include<cmath>
#include<algorithm>
#include<cctype>
#include<iomanip>
using namespace std;

struct node
{
    int num;
    int son[26];
}trie[100000];
int ans,cnt,tot,len;
char c;
char s[100];

inline void zql()
{
    int pos=0;
    for(int i=0;i<len;i++)
    {
        if(!trie[pos].son[s[i]-'a'])
            trie[pos].son[s[i]-'a']=++tot;      //計算。。。各種個數
        pos=trie[pos].son[s[i]-'a'];
    }
    trie[pos].num++;
}

int main()
{
    //freopen("assess.in","r",stdin);
    //freopen("assess.out","w",stdout);

    memset(s,0,sizeof(s));
    while(c=getchar())
    {
        if(c<1||c>128)
            break;        //若不是字符,退出循環。
        len=0;
        while((c<'A'||c>'Z')&&(c<'a'||c>'z'))
        {
            c=getchar();
            if(c<1||c>128)
                break;
        }
        for(;c>='a'&&c<='z'||c>='A'&&c<='Z';c=getchar())
        {
            if(c>='A'&&c<='Z')
                c+=32;           //大寫字母改小寫。
            s[len++]=c;
        }
        if(len!=0)
        {
            cnt++;
            zql();
        }
    }
    for(int i=1;i<=tot;i++)
        if(trie[i].num)
            ans+=pow(trie[i].num,4);   //最終計算。
    cout<<ans<<" "<<cnt;
    return 0;
}

2.Route

一條直線上有 n 個人在走,有三個值來描述第i個人的行爲:t[i],s[i],f[i],分別表示他出發的時間,他的起點位置和終點位置。假設每個人走的一樣快,他們每個單位時間只會朝目的地走一個單位的距離。
當兩個人相遇的時候,他們相互之間會打招呼。按照常理,兩個人之間最多隻會打一次招呼。
請算出每個人在他的旅程中要和多少個人打招呼。
注意:
(1)某個人在出發前是不在直線上的;
(2)到終點後,這個人也不再出現在直線上;
(3)如果 2 個人在同一個位置、同一時刻出發,屬於相遇的情況。

輸入格式

輸入第一行包括一個整數 n 表示人數。
接下來 n 行,每行三個整數 t[i],s[i],f[i]。

輸出格式

一行 n 個整數。第 i 個整數 a[i] 表示第 i 個人總共要和 a[i] 個人(總人數)打招呼。

樣例數據

輸入
3
1 1 10
5 8 2
9 9 10

輸出
2 1 1

備註

【樣例說明】

這裏寫圖片描述

【數據範圍】
對 30% 的輸入數據 :n≤10
對 100% 的輸入數據 :n≤1000,1≤t[i],s[i],f[i]≤1000000,s[i]≠f[i]

當時,想得太簡單了,雖然實際上也沒有多難。。。。。
唔,首先方向是關鍵,關係着兩個人是同向還是相向。
若是同向,則相遇後後面的路程必然完全一樣,則兩人到達靠終點方向近的那個起點的時候,所用時間必然一樣。
若是反向,先記錄下兩人的起點和終點一共四個值,只有中間一段重疊時二者纔有可能相遇,則給四個點排個序,用b數組存儲,若二者相遇,則必然有 abs(b[1]-b[2])<=2×(b[3]-b[2])&&abs(b[3]-b[4])<=2×(b[3]-b[2]) 恆成立。(具體的由於不方便畫圖,可以自己推吶。。)

#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<string>
#include<ctime>
#include<cmath>
#include<algorithm>
#include<cctype>
#include<iomanip>
using namespace std;

struct node
{
    int t,s,f,bb;
}a[1010];
int n,d,t1,t2,t3,t4;
int ans[1010],b[5];

inline int read()
{
    int i=0,f=1;
    char ch;
    for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar());
    if(ch=='-') 
    {
        ch=getchar();
        f=-1;
    }
    for(;ch>='0'&&ch<='9';ch=getchar()) 
        i=(i<<3)+(i<<1)+ch-'0';
    return i*f;
}

inline bool zql(int x,int y)
{
    if(max(a[x].s,a[x].f)<min(a[y].s,a[y].f))  //排除掉必然不可能的
        return false;
    if(max(a[y].s,a[y].f)<min(a[x].s,a[x].f))
        return false;
    return true;
}

int main()
{
    n=read();
    for(int i=1;i<=n;i++)
    {
        a[i].t=read();
        a[i].s=read();
        a[i].f=read();
        if(a[i].s<a[i].f)
            a[i].bb=1;
        else                     //記錄方向。
            a[i].bb=2;
    }
    for(int i=1;i<=n;i++)
        for(int j=i+1;j<=n;j++)
            if(zql(i,j)==true)
            {
                if(a[i].bb==a[j].bb)
                {
                    if(a[i].bb==1)
                        d=max(a[i].s,a[j].s);
                    else                         //同向。
                        d=min(a[i].s,a[j].s);
                    t1=a[i].t+abs(a[i].s-d);
                    t2=a[j].t+abs(a[j].s-d);
                    if(t1==t2)
                        ans[i]++,ans[j]++;
                }
                else
                {
                                                                                b[1]=a[i].s,b[2]=a[i].f,b[3]=a[j].s,b[4]=a[j].f;
                    sort(b+1,b+4+1);
                    t1=a[i].t+abs(a[i].s-b[2]);
                    t2=a[j].t+abs(a[j].s-b[2]);   //反向。
                    t3=a[i].t+abs(a[i].s-b[3]);
                    t4=a[j].t+abs(a[j].s-b[3]);
                    if(abs(t1-t2)<=2*(b[3]-b[2])&&abs(t3-t4)<=2*(b[3]-b[2]))
                        ans[i]++,ans[j]++;
                }
            }
    for(int i=1;i<=n;i++)
        cout<<ans[i]<<" ";
    return 0;
}

3.Work

假設現在離 noip 還有 m 天,有 n 個人要去參加比賽。他們每個人都有一個預定的訓練量 r[i] ,所以每一天他們都抓緊時間練習。但是由於條件限制,第 i 天只有 t[i] 的時間可以練習。
我們都知道,一個人在開始幹活以前總要浪費一些時間做一些雜七雜八的事情。現在我們假定第 i 個人每天在訓練前浪費的時間是固定的,記爲 d[i] 。這段浪費掉的時間過後,選手會專心致志訓練,他們會充分利用剩下的時間。然而一個可能的情況時,一個人還在無所事事的時候,某一天的訓練時間已經過去了,所以他那一天什麼事情都沒有做。
現在請問每個人在第幾天的時候可以完成自己的訓練任務。當然會存在志向遠大但是很懶惰的人到最後也是做不完的情況。

輸入格式

第一行兩個整數 n,m ,表示人數和天數 。
接下來一行 m 個整數 t[i] 。
接下來 n 行每行兩個整數 d[i],r[i] 。

輸出格式

一行輸出 n 個整數表示每個人在第幾天可以完成自己的工作,如果完不成,輸出 0 。

樣例數據
輸入 
3 3
4 2 5
1 3
2 5
3 4

輸出
1 3 0

備註

【數據範圍】
對 30% 的輸入數據 :1≤n,m≤1000
對 100% 的輸入數據 :1≤n,m≤ 200000;1≤t[i]≤1000000; 0≤d[i]≤1000000;1≤r[i]≤1000000

【注意事項】
如果某人浪費的時間超過一天,不需減去負的時間。

哦忘了說上面第二題用的是trie樹,這一題呢,用的是樹狀數組。
嗯。

#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<string>
#include<ctime>
#include<cmath>
#include<algorithm>
#include<cctype>
#include<iomanip>
using namespace std;

struct node
{
    int t,num,r;
}d[200103],man[200103];
int n,m;
int tim[200103],ans[200103];
long long sum[200103];

inline bool comp(const node &a,const node &b)
{
    if(a.t==b.t)
        return a.num<b.num;
    return  a.t>b.t;
}

inline int lowbit(int x)
{
    return x&(-x);
}

inline void build(int x,int val)
{
    for(int i=x;i<=m;i+=lowbit(i))
    {
        sum[i]+=val;
        tim[i]++;
    }
}

inline bool check(int x,int id)
{
    int res=0;
    for(int i=x;i>=1;i-=lowbit(i))
    {
        res+=sum[i];
        res-=man[id].t*tim[i];
    }
    return res>=man[id].r;
}

int main()
{
    //freopen("work.in","r",stdin);
    //freopen("work.out","w",stdout);

    cin>>n>>m;
    for(int i=1;i<=m;i++)
    {
        cin>>d[i].t;
        d[i].num=i;
    }
    for(int i=1;i<=n;i++)
    {
        cin>>man[i].t>>man[i].r;
        man[i].num=i;
    }
    sort(d+1,d+m+1,comp);
    sort(man+1,man+n+1,comp);
    int cnt=1;
    for(int i=1;i<=n;i++)
    {
        while(man[i].t<d[cnt].t)
        {
            build(d[cnt].num,d[cnt].t);
            cnt++;
        }
        int l=1,r=m;
        ans[man[i].num]=0;
        while(l<=r)
        {
            int mid=(l+r)/2;
            if(check(mid,i))
                ans[man[i].num]=mid,r=mid-1;
            else l=mid+1;
        }
    }
    for(int i=1;i<=n;i++)
        cout<<ans[i]<<" ";
    return 0;
}

真的好冷啊這幾天。。。。
來自2017.10.9.

——我認爲return 0,是一個時代的終結。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章