1. 程式人生 > >7.29NOIP模擬賽

7.29NOIP模擬賽

include char s 人做 數量 代碼 pac 描述 不同 區間

7.29NOIP模擬賽

T1

YSG (1s,64MB,ysg.in,ysg.out)

描述

ysg,yxy,azw 三人正在刷題。

他們每做一題的時間都是一個有理數。

如果在某一時刻,三人同時做完一道 題,那麽,他們會開始談笑風生。

現在,他們想知道,從時刻 0 開始,至少要等多久才能談笑風生。

輸入格式

一行 6 個整數 a1,b1,a2,b2,a3,b3,其中 ysg 每做一道題的時間是 a1/b1,

yxy 是 a2/b2,azw 是 a3/b3。不保證 a,b 互質。

輸出格式

一行 2 個數 c,d,表示第一次談笑風生是在時刻 c/d。其中 c,d 互質。

輸入樣例

3 6 4 5 3 1

輸出樣例

12 1

樣例解釋

在時刻 12,ysg 做了 24 道題,yxy 做了 15 道題,azw 做了 4 道題,他們開始 談笑風生

備註

對於 30%的數據,b1=b2=b3=1。 對於 100%的數據,a1,a2,a3,b1,b2,b3<=100

題解:

先將三個分數化簡,

再三個分數通分(可以求最小公倍數,也可以分母直接相乘),同時乘以d,

求出通分後的數的最小公倍數c,

c/d化簡一下即為答案

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 using namespace std;
 5 int a1,b1,a2,b2,a3,b3;
 6 inline int gcd(int x,int y){
 7     if(y>x) swap(x,y);
 8     if(y==0) return x;
 9     return gcd(y,x%y);
10 }
11 inline void huajian(int &x,int &y){
12     int g=gcd(x,y);
13     x/=g; y/=g;
14 }
15 inline int get_lcm(int a,int b,int c){
16     int l1=a*b/gcd(a,b);
17     return l1*c/gcd(l1,c);
18 }
19 int main()
20 {
21     freopen("ysg.in","r",stdin);
22     freopen("ysg.out","w",stdout);
23     scanf("%d%d%d%d%d%d",&a1,&b1,&a2,&b2,&a3,&b3);
24     huajian(a1,b1);
25     huajian(a2,b2);
26     huajian(a3,b3);
27     int lcm1=get_lcm(b1,b2,b3);
28     int lcm2=get_lcm(a1*lcm1/b1,a2*lcm1/b2,a3*lcm1/b3);
29     huajian(lcm1,lcm2);
30     printf("%d %d\n",lcm2,lcm1);
31     fclose(stdin); fclose(stdout);
32     return 0;
33 }

T2

YXY (1s,128MB,yxy.in,yxy.out)

問題描述

ysg,yxy,azw 三人正在刷題。

OJ 上一共有 n 道題,然而因為有的題的算法有人不會,所以他們決定每人做一道題。

現在他們已經分配好了做題任務,把每道題都指定給一個人做

但是如果有 人做的題數量比其他人多,他就會感覺不爽。

為了避免這種情況,他們只好選一些題不做,但是為了美觀,他們做的題目 必須是連續一段。

他們現在想知道,有多少種選擇的方案滿足條件。

輸入格式

輸入數據有 n 行,每行一個字符串,為”ysg”,”yxy”,”azw”中的一個,

第 i 行代 表做第 i 題的人的名字。

輸出格式

輸出有多少種選擇的方案

輸入樣例

ysg
yxy
azw
azw
yxy
azw
yxy
ysg
yxy
ysg
ysg

輸出樣例

3

樣例說明

有三種方案,選 1~3 一段,選 6~8 一段,選 3~11 一段

每一段內三個名字,出現次數一樣多

數據範圍

對於 20%的數據,n <= 100。

對於 40%的數據,n <= 1000。

對於 100%的數據,n <= 100000

題解:

40pts:

搞三個前綴和數組,分別維護三個名字的出現次數

O(n^2)查詢,若一段區間內三個名字的出現次數相同,ans++

100pts:

從左到右掃一遍,記錄兩個值:

delta1:以now為結尾的前綴中ysy出現的次數-yxy出現的次數

delta2:以now為結尾的前綴中yxy出現的次數-azw出現的次數

顯然,若在兩個不同的位置l和r,delta1(l)==delta(r)且delta2(l)==delta2(r),

說明從l到r三個名字出現的次數是一樣的,ans++

用map維護即可

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 #include<map>
 5 using namespace std;
 6 #define N 100000
 7 map<int,int> a[N*2+20];
 8 int n,d1=N,d2=N,ans;
 9 int main()
10 {
11     a[N][N]=1; char s[5];
12     while(scanf("%s",s)!=EOF){
13         if(s[0]==‘y‘)
14          if(s[1]==‘s‘)
15           d1++;
16          else {
17              d1--; d2++;
18          }
19         else d2--;
20         ans+=a[d1][d2];
21         a[d1][d2]++;
22     }
23     printf("%d\n",ans);
24     return 0;
25 }

T3

AZW (2s,256MB,azw.in,azw.out)

問題描述

ysg,yxy,azw 三人正在刷題

在他們刷題的 oj 上,除第 0 題外,每道題都有一個父親(父親的編號不一定 比他自己小)

所以可以把這些題看成一個樹形的結構。

他們在接下來的 m 天中,每天要麽做一道新題,要麽瀏覽一些題。

瀏覽的方法是:

先選兩道題 x,y,然後把這兩道題之間路徑上的題全部瀏覽一遍。

在瀏覽的時候,他們有時會發現一道題似曾相識,可又想不起何時做過

原來是他們做這道題的時間太過久遠,以致記憶的模糊。

具體來說,如果一道題做 題時間距離瀏覽的時間已經超過了他們當天的記憶力,

他們就會出現這樣的情況 (具體看樣例)。

所以,現在對於每次瀏覽,他們想知道,這次瀏覽會看多少道題,以及有多少題似曾相識。

輸入格式

第一行一個數 n,代表 oj 上有 n+1 題(從 0 到 n)。

第二行 n 個數,表示第 i 道題的父親的編號。

第三行一個數 m,代表一共 m 天 接下來 m 行,先是一個數 1 或者 2,如果是 1,後面接三個數 x,y,c,表示當 天的瀏覽從 x 到 y,當天記憶力為 c,否則後面接一個數 x,表示當天做了第 x 題

輸出格式

對於每次瀏覽,輸出一行兩個數,表示這次瀏覽會看多少道題,以及有多少 題似曾相識。

輸入樣例

7
0 1 1 2 2 3 3
6
1 4 7 0
2 1
2 4
2 7
1 4 7 1
1 4 7 3

輸出樣例

5 0
5 2
5 1

樣例說明

3 次都是瀏覽 5 道題,分別是 4 號、2 號、1 號、3 號和 7 號。

其中,對於第 1 天,所有題都沒有做過;

對於第 5 天,有 2 道題似曾相識,分別是 1 號和 4 號, 7 號雖然做過,但只隔 1 天,剛好等於記憶力,所以還想得起;

對於第 6 天,只有 1 號似曾相識。

數據範圍

對於 20%的數據,n <= 100,m<=100。

對於 40%的數據,n <= 2000,m<=2000。

另有 20%的數據,沒有做題的操作

另有 20%的數據,雖有做題操作,但每天的記憶力都是 0

對於100%的數據,n <= 200000,m<=200000,保證一道題不會做兩遍

題解:

40pts:dfs暴力在樹上走,每路過一個點就看他是不是之前做過,是在什麽時候做的。
60pts:40+加上求lca,
80pts:60+樹鏈剖分/dfs序,求路徑上有多少做過的題
100pts:就是相當於先把每個點是在什麽時候被做的預處理出來,然後每次詢問一條鏈上面被做時間小於一個給定數的點有多少個,用樹上主席樹。

別人的代碼:

 1 #include<cstdio>
 2 #include<vector>
 3 #include<algorithm>
 4 #define N 200011
 5 using namespace std;
 6 
 7 int n,m,a1[N],a2[N],a3[N],a4[N];
 8 int cc[N],c[20*N][2],z[20*N],t;
 9 vector<int>g[N];
10 int s[N],f[20][N],d[N];
11 int lca(int u,int v){
12     if(d[u]<d[v])swap(u,v);
13     for(int i=17;~i;i--)
14         if(1<<i<=d[u]-d[v])
15             u=f[i][u];
16     if(u==v)return u;
17     for(int i=17;~i;i--)
18         if(f[i][u]^f[i][v])
19             u=f[i][u],v=f[i][v];
20     return f[0][u];
21 }
22 int cx(int o,int p){
23     int ans=0;
24     for(int l=1,r=m;l^r;)
25         if(p>l+r>>1)ans+=z[c[o][0]],
26             o=c[o][1],l=(l+r>>1)+1;
27         else o=c[o][0],r=l+r>>1; 
28     return ans;
29 }
30 int main(){
31     scanf("%d",&n);
32     t=++n;
33     for(int i=2;i<=n;i++){
34         scanf("%d",&f[0][i]);
35         g[++f[0][i]].push_back(i);
36     }
37     scanf("%d",&m);
38     for(int i=1;i<=n;i++)
39         cc[i]=m;
40     for(int i=1;i<=m;i++){
41         scanf("%d",&a1[i]);
42         if(a1[i]==1)scanf("%d%d%d",&a2[i],&a3[i],&a4[i]),a2[i]++,a3[i]++;
43         else scanf("%d",&a2[i]),cc[++a2[i]]=i;
44     }
45     d[1]=1;
46     for(s[s[0]=1]=1;s[0];){
47         int u=s[s[0]--];
48         z[u]=z[f[0][u]]+1;
49         for(int o=u,oo=f[0][u],l=1,r=m;l^r;){
50             int w=cc[u]>l+r>>1;
51             if(w)l=(l+r>>1)+1;
52             else r=l+r>>1;
53             c[o][w^1]=c[oo][w^1];
54             o=c[o][w]=++t,oo=c[oo][w];
55             z[o]=z[oo]+1;
56         }
57         for(int i=0;i<g[u].size();i++)
58             d[g[u][i]]=d[u]+1,s[++s[0]]=g[u][i];
59     }
60     for(int k=0;1<<k<n;k++)
61         for(int i=1;i<=n;i++)
62             f[k+1][i]=f[k][f[k][i]];
63     for(int i=1;i<=m;i++)
64         if(a1[i]==1){
65             int u=a2[i],v=a3[i],w=lca(u,v),p=i-a4[i];
66             printf("%d %d\n",d[u]+d[v]-2*d[w]+1,cx(u,p)+cx(v,p)-cx(w,p)-cx(f[0][w],p));
67         }
68 }

7.29NOIP模擬賽