纪中游记(五)

20190807

T0

出现了,时限4s的题目!直接暴力。

结果爆零。

T1

调了两个小时的代码,竟在考试的最后时刻证明为错解,心态大崩。

其实这道题只需要用线段树或是树状数组模拟就可以AC,简直是模板题。

在这里只解释一下树状数组的思路(其实线段树也差不多)

先读一遍题,可以发现“阶段”其实就是把 数 移出数组,对其它数的步数产生影响;再思考一下,这不就是树状数组所支持的单点修改么?

如果你没有思路,那么我们跑一遍样例:

首先记录每个数的位置记做wei[i],预处理两个树状数组(加一)

接着在按题目要求依次处理每个阶段的数,把树状数组对应的位置减一

 

但为什么是两个树状数组呢,实际上处于偶阶段的数会向后移,奇阶段的数会向前移,这时一个树状数组调用起来就非常麻烦,不如再添加一个来维护后缀和,同步修改,分别查询。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int tru[100005],fal[100005];
 4 int n,wei[100005];
 5 void add1(int x,int ui)
 6 {
 7     while(x<=n)
 8     {
 9         tru[x]+=ui;
10         x+=x&(-x);
11     }
12 }
13 void add2(int x,int ui)
14 {
15     int op=n-x+1;
16     while(op<=n)
17     {
18         fal[op]+=ui;
19         op+=op&(-op);
20     }
21 }
22 int ask1(int x)
23 {
24     int num=0;
25     while(x)
26     {
27         num+=tru[x];
28         x-=x&(-x);
29     }
30     return num;
31 }
32 int ask2(int x)
33 {
34     int num=0,op=n-x+1;
35     while(op)
36     {
37         num+=fal[op];
38         op-=op&(-op);
39     }
40     return num;
41 }
42 inline int read()
43 {
44     int x=0;
45     char ch=getchar();
46     while(ch<'0'||ch>'9')
47     {
48         ch=getchar();
49     }
50     while(ch>='0'&&ch<='9')
51     {
52         x=(x<<1)+(x<<3)+ch-'0';
53         ch=getchar();
54     }
55     return x;
56 }
57 int main()
58 {
59     scanf("%d",&n);
60     for(int i=1;i<=n;i++)
61     {
62         int op=read();
63         wei[op]=i;
64         add1(i,1);
65         add2(i,1);
66     }
67     int zu=(n+1)/2;
68     for(int i=1;i<zu;i++)
69     {
70         add1(wei[i],-1);add2(wei[i],-1);
71         printf("%d\n",ask1(wei[i]));
72         add2(wei[n-i+1],-1);add1(wei[n-i+1],-1);
73         printf("%d\n",ask2(wei[n-i+1]));
74     }
75     if(n&1)
76     {
77         printf("0");
78     }
79     else
80     {
81         add1(wei[zu],-1);
82         printf("%d\n",ask1(wei[zu]));
83         printf("0");
84     }
85     return 0;
86 }
索然无味的代码环节

又一道裸树状数组。

posted @ 2019-08-09 19:42  HHHG  阅读(133)  评论(0编辑  收藏  举报