HNOI 2016 省队集训日记

第一天



DeepDarkFantasy

从东京出发,不久便到一处驿站,写道:日暮里。  ——鲁迅《藤野先生》

定义一个置换的平方为对1~n的序列做两次该置换得到的序列。已知一个置换的平方,并且这个结果是一个排列,求该置换。

输入第一行一个数n表示排列长度,接下来一行n个数描述排列。

有解则输出一行n个数表示原排列。否则输出一行一个-1。


测试点编号


特征


0~1


n<=10


2~9


n<=1000000

此题有spj。



  考试的时候懵逼了,根本没想清就开始乱打。

  题解:由题易得每一个置换相当于一个n个点n条边的图,那么相当于是已知每个点在图上走两步的终点,求这个图。于是我们可以很快的得到,无论图中的环是奇环还是偶环,最终得到的答案都会是偶环。然后对于两种不同的情况分类讨论一下就可以得到解法了。

  代码写丑了,虽然是O(N)的,但因为常数问题没能过。

 1 #include <algorithm>
 2 #include <iostream>
 3 #include <cstring>
 4 #include <cstdio>
 5 using namespace std;
 6 const int maxn=1000010;
 7 int a[maxn],num[maxn];
 8 int ans[maxn],p[maxn];
 9 int b[maxn],n;
10 int st[maxn],top;
11 int vis[maxn],c[maxn];
12 bool cmp(int x,int y){
13     return num[x]<num[y];
14 }
15
16 int main(){
17 #ifndef ONLINE_JUDGE
18     freopen("deepdarkfantasy.in","r",stdin);
19     freopen("deepdarkfantasy.out","w",stdout);
20 #endif
21     scanf("%d",&n);
22     for(int i=1,x;i<=n;i++){
23         scanf("%d",&x);
24         a[x]=i;p[i]=i;
25     }
26     int x,y,t,q,tot;
27     for(int i=1;i<=n;i++){
28         if(a[i]==i){
29             b[i]=i;
30             continue;
31         }
32         if(!vis[i]){
33             x=i,tot=0;
34             while(!vis[x]){
35                 tot+=1;
36                 vis[x]=1;
37                 x=a[x];
38             }
39             st[++top]=x;
40             num[top]=tot;
41             c[tot]+=1;
42         }
43     }
44     for(int i=1;i<=n;i++)
45         if(i%2==0&&c[i]%2){
46             printf("-1\n");
47             return 0;
48         }
49     sort(p+1,p+top+1,cmp);
50     for(int i=1;i<=top;i++){
51         x=p[i],t=st[x];
52         if(num[x]%2){
53             for(int j=1,k=1;j<=num[x];j++){
54                 ans[k]=t;
55                 t=a[t];k+=2;
56                 if(k>num[x])k=2;
57             }
58             ans[0]=ans[num[x]];
59             for(int j=1;j<=num[x];j++)
60                 b[ans[j-1]]=ans[j];
61         }
62         else{
63             y=p[++i],q=st[y];
64             for(int j=1;j<=2*num[x];j++){
65                 if(j%2){
66                     ans[j]=t;
67                     t=a[t];
68                 }
69                 else{
70                     ans[j]=q;
71                     q=a[q];
72                 }
73             }
74             ans[0]=ans[2*num[x]];
75             for(int j=1;j<=2*num[x];j++)
76                 b[ans[j-1]]=ans[j];
77         }
78     }
79     for(int i=1;i<=n;i++)
80         printf("%d ",b[i]);
81     printf("\n");
82     return 0;
83 }


Wallace

 

“看来华莱士先生不太懂历史和哲♂学”  ——自长者与美国记者华莱士的谈话

有两颗各含N个点的无根树,每棵树中点分别被编号为0,1,2,....,N-1;注意两棵树并不保证同构。另外给一个N长的整数数组Score[],记录N个编号的得分,Score中的每个元素可正可负。问题的任务是寻找 集合{0,1,2,3,4,...,N-1}的一个最优子集subset(可以是空集),要求满足以下条件:

1)在第一棵树中,subset中包含的编号对应的点能构成一个连通的子图;即去掉这棵树中所有subset中不包含的点后,剩下的点依然是一棵连通的树。

2)在第二棵树中,subset中包含的编号对应的点也能构成一个连通的子图;

3)使subset包含编号的总得分尽可能的大;即SUM{ Score[i] | i∈subset }能取到尽可能大的值。

输入第一行一个正整数N。第二行N个整数Score[]代表0~N-1每个点的权值。

后面N-1行每行两个整数u,v代表第一棵树里面u点和v点之间有连边。

再后面N-1行每行两个整数u,v代表第二棵树里面u点和v点之间有连边。

输出一行一个整数代表这个subset包含编号的总分的最大值。


测试点编号


特征


0~5


n<=15


6~9


两棵树形状与编号完全相同


12~24


2<=n<=50且|Score[i]|<=1000且0<=u,v<n

  这道题并不是很难,枚举一个点必选,则可以用网络流做。

  1 #include <iostream>
  2 #include <cstring>
  3 #include <cstdio>
  4 #include <queue>
  5 using namespace std;
  6
  7 const int maxn=510;
  8 const int maxm=1000010;
  9 const int INF=100000000;
 10 int cnt,tot,fir[maxn],fron[maxn],dis[maxn];
 11 int to[maxm],nxt[maxm],gap[maxn],path[maxn];
 12 int cap[maxm];queue<int>q;
 13
 14 struct Max_Flow{
 15     void Init(int tot_=0){
 16         tot=tot_;cnt=1;
 17         memset(fir,0,sizeof(fir));
 18         memset(dis,0,sizeof(dis));
 19         memset(gap,0,sizeof(gap));
 20     }
 21
 22     void add(int a,int b,int c){
 23         nxt[++cnt]=fir[a];
 24         fir[a]=cnt;
 25         cap[cnt]=c;
 26         to[cnt]=b;
 27     }
 28
 29     void addedge(int a,int b,int c){
 30         add(a,b,c);
 31         add(b,a,0);
 32     }
 33
 34     bool BFS(int s,int t){
 35         dis[t]=1;q.push(t);
 36         while(!q.empty()){
 37             int x=q.front();q.pop();
 38             for(int i=fir[x];i;i=nxt[i])
 39                 if(!dis[to[i]]){
 40                     dis[to[i]]=dis[x]+1;
 41                     q.push(to[i]);
 42                 }
 43         }
 44         return dis[s];
 45     }
 46
 47     int Aug(int s,int t,int &p){
 48         int f=INF;
 49         while(p!=s){
 50             f=min(f,cap[path[p]]);
 51             p=to[path[p]^1];
 52         }p=t;
 53         while(p!=s){
 54             cap[path[p]]-=f;
 55             cap[path[p]^1]+=f;
 56             p=to[path[p]^1];
 57         }
 58         return f;
 59     }
 60
 61     int ISAP(int s,int t){
 62         if(!BFS(s,t))return 0;
 63         for(int i=s;i<=t;i++)fron[i]=fir[i];
 64         for(int i=s;i<=t;i++)gap[dis[i]]+=1;
 65         int p=s,ret=0;
 66         while(dis[s]<=tot){
 67             if(p==t)ret+=Aug(s,t,p);
 68
 69             for(int &i=fron[p];i;i=nxt[i])
 70                 if(cap[i]&&dis[p]==dis[to[i]]+1){
 71                     path[p=to[i]]=i;
 72                     break;
 73                 }
 74
 75             if(!fron[p]){
 76                 if(--gap[dis[p]]==0)
 77                     break;
 78                 int Min=tot;
 79                 for(int i=fir[p];i;i=nxt[i])
 80                     if(cap[i])Min=min(Min,dis[to[i]]);
 81                 gap[dis[p]=Min+1]+=1;fron[p]=fir[p];
 82                 if(p!=s)p=to[path[p]^1];
 83             }
 84         }
 85         return ret;
 86     }
 87 }isap;
 88
 89 int w[maxn],n;
 90 int G[maxn][maxn];
 91 int G2[maxn][maxn];
 92 int dep[maxn],pre[maxn];
 93
 94 void Build(int x,int y){
 95     int py=y;
 96     while(x!=py){
 97         if(dep[x]>dep[py]){
 98             x=pre[x];
 99             isap.addedge(y,x,INF);
100         }
101         else{
102             py=pre[py];
103             isap.addedge(y,py,INF);
104         }
105     }
106 }
107
108 int DFS(int x,int fa){
109     int ret=0;
110     if(w[x]>=0){
111         isap.addedge(0,x,w[x]);
112         ret+=w[x];
113     }
114     else isap.addedge(x,n+1,-w[x]);
115     for(int i=1;i<=n;i++)
116         if(G[x][i]&&i!=fa){
117             isap.addedge(i,x,INF);
118             Build(x,i);ret+=DFS(i,x);
119         }
120     return ret;
121 }
122
123 void Prepare(int x,int fa){
124     for(int i=1;i<=n;i++)
125         if(G2[x][i]&&i!=fa){
126             dep[i]=dep[x]+1;
127             pre[i]=x;Prepare(i,x);
128         }
129 }
130
131 int main(){
132     freopen("wallace.in","r",stdin);
133     freopen("wallace.out","w",stdout);
134     scanf("%d",&n);
135     for(int i=1;i<=n;i++)
136         scanf("%d",&w[i]);
137     for(int i=1,a,b;i<n;i++){
138         scanf("%d%d",&a,&b);
139         G[a+1][b+1]=G[b+1][a+1]=1;
140     }
141     for(int i=1,a,b;i<n;i++){
142         scanf("%d%d",&a,&b);
143         G2[a+1][b+1]=G2[b+1][a+1]=1;
144     }Prepare(1,0);
145     int ans=0,tmp;
146     for(int i=1;i<=n;i++){
147         isap.Init(n+2);tmp=DFS(i,0);
148         ans=max(ans,tmp-isap.ISAP(0,n+1));
149     }
150     printf("%d\n",ans);
151     return 0;
152 }

第二天



永不落幕的 永不落幕的 zy
【背景】
人们的感情像洪水一样袭来,头晕目眩。 人们的感情像洪水一样袭来,头晕目眩。 人们的感情像洪水一样袭来,头晕目眩。 人们的感情像洪水一样袭来,头晕目眩。 人们的感情像洪水一样袭来,头晕目眩。 人们的感情像洪水一样袭来,头晕目眩。 人们的感情像洪水一样袭来,头晕目眩。 人们的感情像洪水一样袭来,头晕目眩。
【题目 描述】 描述】
zy 是一位拥有“共感”能力的少年,他总意无地知别人心情。 是一位拥有“共感”能力的少年,他总意无地知别人心情。 是一位拥有“共感”能力的少年,他总意无地知别人心情。 是一位拥有“共感”能力的少年,他总意无地知别人心情。 是一位拥有“共感”能力的少年,他总意无地知别人心情。 是一位拥有“共感”能力的少年,他总意无地知别人心情。 是一位拥有“共感”能力的少年,他总意无地知别人心情。 是一位拥有“共感”能力的少年,他总意无地知别人心情。 是一位拥有“共感”能力的少年,他总意无地知别人心情。 是一位拥有“共感”能力的少年,他总意无地知别人心情。 是一位拥有“共感”能力的少年,他总意无地知别人心情。 是一位拥有“共感”能力的少年,他总意无地知别人心情。 是一位拥有“共感”能力的少年,他总意无地知别人心情。 是一位拥有“共感”能力的少年,他总意无地知别人心情。 是一位拥有“共感”能力的少年,他总意无地知别人心情。 是一位拥有“共感”能力的少年,他总意无地知别人心情。 sm 是一位 是一位 有着“心墙”的少女,她感情无法传递出去。就像命运一般他们相遇了仿佛 有着“心墙”的少女,她感情无法传递出去。就像命运一般他们相遇了仿佛 有着“心墙”的少女,她感情无法传递出去。就像命运一般他们相遇了仿佛 有着“心墙”的少女,她感情无法传递出去。就像命运一般他们相遇了仿佛 有着“心墙”的少女,她感情无法传递出去。就像命运一般他们相遇了仿佛 有着“心墙”的少女,她感情无法传递出去。就像命运一般他们相遇了仿佛 有着“心墙”的少女,她感情无法传递出去。就像命运一般他们相遇了仿佛 有着“心墙”的少女,她感情无法传递出去。就像命运一般他们相遇了仿佛 有着“心墙”的少女,她感情无法传递出去。就像命运一般他们相遇了仿佛 有着“心墙”的少女,她感情无法传递出去。就像命运一般他们相遇了仿佛 有着“心墙”的少女,她感情无法传递出去。就像命运一般他们相遇了仿佛 有着“心墙”的少女,她感情无法传递出去。就像命运一般他们相遇了仿佛 有着“心墙”的少女,她感情无法传递出去。就像命运一般他们相遇了仿佛 有着“心墙”的少女,她感情无法传递出去。就像命运一般他们相遇了仿佛 有着“心墙”的少女,她感情无法传递出去。就像命运一般他们相遇了仿佛 有着“心墙”的少女,她感情无法传递出去。就像命运一般他们相遇了仿佛 有着“心墙”的少女,她感情无法传递出去。就像命运一般他们相遇了仿佛 zy (的 能力)就是为了 能力)就是为了 能力)就是为了 能力)就是为了 sm 而存在一样(事实上也确如此)。 而存在一样(事实上也确如此)。 而存在一样(事实上也确如此)。 而存在一样(事实上也确如此)。 而存在一样(事实上也确如此)。 而存在一样(事实上也确如此)。 而存在一样(事实上也确如此)。 而存在一样(事实上也确如此)。 而存在一样(事实上也确如此)。
sm 的心墙由许多迷茫组成,每个都希望从 的心墙由许多迷茫组成,每个都希望从 的心墙由许多迷茫组成,每个都希望从 的心墙由许多迷茫组成,每个都希望从 的心墙由许多迷茫组成,每个都希望从 的心墙由许多迷茫组成,每个都希望从 的心墙由许多迷茫组成,每个都希望从 的心墙由许多迷茫组成,每个都希望从 的心墙由许多迷茫组成,每个都希望从 的心墙由许多迷茫组成,每个都希望从 X轴上某一点去到另,而只有 轴上某一点去到另,而只有 轴上某一点去到另,而只有 轴上某一点去到另,而只有 轴上某一点去到另,而只有 轴上某一点去到另,而只有 轴上某一点去到另,而只有 zy 能 消除 sm 的迷茫。面对数量如此庞大, 的迷茫。面对数量如此庞大, 的迷茫。面对数量如此庞大, 的迷茫。面对数量如此庞大, 的迷茫。面对数量如此庞大, 的迷茫。面对数量如此庞大, 的迷茫。面对数量如此庞大, 的迷茫。面对数量如此庞大, zy 不曾想要放弃,但有些迷失了方向。 不曾想要放弃,但有些迷失了方向。 不曾想要放弃,但有些迷失了方向。 不曾想要放弃,但有些迷失了方向。 不曾想要放弃,但有些迷失了方向。 不曾想要放弃,但有些迷失了方向。 不曾想要放弃,但有些迷失了方向。 不曾想要放弃,但有些迷失了方向。
假设现在时间是 假设现在时间是 假设现在时间是 假设现在时间是 0,zy 在心墙的 在心墙的 在心墙的 1位置, 位置, zy 每单位时间的移动速度是 每单位时间的移动速度是 每单位时间的移动速度是 每单位时间的移动速度是 每单位时间的移动速度是 每单位时间的移动速度是 1。
若现在 若现在 zy 携带的迷茫想要去地点和心墙上剩下中在他右边个数大于等左 携带的迷茫想要去地点和心墙上剩下中在他右边个数大于等左 携带的迷茫想要去地点和心墙上剩下中在他右边个数大于等左 携带的迷茫想要去地点和心墙上剩下中在他右边个数大于等左 携带的迷茫想要去地点和心墙上剩下中在他右边个数大于等左 携带的迷茫想要去地点和心墙上剩下中在他右边个数大于等左 携带的迷茫想要去地点和心墙上剩下中在他右边个数大于等左 携带的迷茫想要去地点和心墙上剩下中在他右边个数大于等左 携带的迷茫想要去地点和心墙上剩下中在他右边个数大于等左 携带的迷茫想要去地点和心墙上剩下中在他右边个数大于等左 携带的迷茫想要去地点和心墙上剩下中在他右边个数大于等左 携带的迷茫想要去地点和心墙上剩下中在他右边个数大于等左 携带的迷茫想要去地点和心墙上剩下中在他右边个数大于等左 携带的迷茫想要去地点和心墙上剩下中在他右边个数大于等左 携带的迷茫想要去地点和心墙上剩下中在他右边个数大于等左 携带的迷茫想要去地点和心墙上剩下中在他右边个数大于等左 边,则 边,则 zy 会向右移动,反之左。若现在 会向右移动,反之左。若现在 会向右移动,反之左。若现在 会向右移动,反之左。若现在 会向右移动,反之左。若现在 会向右移动,反之左。若现在 会向右移动,反之左。若现在 会向右移动,反之左。若现在 sm 没有任何迷茫,则 没有任何迷茫,则 没有任何迷茫,则 没有任何迷茫,则 没有任何迷茫,则 zy 原地不动。现在 原地不动。现在 原地不动。现在 原地不动。现在 zy 想 知道,组成心墙的每个迷茫分别在什么时候消失。 知道,组成心墙的每个迷茫分别在什么时候消失。 知道,组成心墙的每个迷茫分别在什么时候消失。 知道,组成心墙的每个迷茫分别在什么时候消失。 知道,组成心墙的每个迷茫分别在什么时候消失。 知道,组成心墙的每个迷茫分别在什么时候消失。 知道,组成心墙的每个迷茫分别在什么时候消失。 知道,组成心墙的每个迷茫分别在什么时候消失。 知道,组成心墙的每个迷茫分别在什么时候消失。 知道,组成心墙的每个迷茫分别在什么时候消失。
为了尽快地让 为了尽快地让 为了尽快地让 zy 能拥抱 能拥抱 sm ,请你帮他。 ,请你帮他。 ,请你帮他。 ,请你帮他。
【输入描述】 【输入描述】
第一行两个数 第一行两个数 第一行两个数 N,M表示迷茫的数量和心墙大小。接下来 表示迷茫的数量和心墙大小。接下来 表示迷茫的数量和心墙大小。接下来 表示迷茫的数量和心墙大小。接下来 表示迷茫的数量和心墙大小。接下来 表示迷茫的数量和心墙大小。接下来 表示迷茫的数量和心墙大小。接下来 表示迷茫的数量和心墙大小。接下来 N行 ,每行 ,每行 ,每3个整 数, t, a,b,表示这个迷茫出现在时刻 ,表示这个迷茫出现在时刻 ,表示这个迷茫出现在时刻 ,表示这个迷茫出现在时刻 ,表示这个迷茫出现在时刻 ,表示这个迷茫出现在时刻 ,表示这个迷茫出现在时刻 t,希望从 ,希望从 a到 b。
【输出描述】 【输出描述】
N行 N个整数,表示每迷茫分别在什么时候消失 个整数,表示每迷茫分别在什么时候消失 个整数,表示每迷茫分别在什么时候消失 个整数,表示每迷茫分别在什么时候消失 个整数,表示每迷茫分别在什么时候消失 个整数,表示每迷茫分别在什么时候消失 个整数,表示每迷茫分别在什么时候消失 个整数,表示每迷茫分别在什么时候消失 个整数,表示每迷茫分别在什么时候消失 个整数,表示每迷茫分别在什么时候消失
【样例输入】 【样例输入】
2 102 102 102 10
1 2 51 2 51 2 51 2 5
7 4 57 4 57 4 57 4 5
【样例输出】 【样例输出】
5
9
【样例解释】 【样例解释】
时刻 1,有迷茫出现了! ,有迷茫出现了! ,有迷茫出现了! ,有迷茫出现了! ,有迷茫出现了!
时刻 2,zy 移动到了位置 移动到了位置 移动到了位置 移动到了位置 2。
时刻 5,zy 移动到了位置 移动到了位置 移动到了位置 移动到了位置 5,迷茫消失。 ,迷茫消失。 ,迷茫消失。
时刻 7,有迷茫出现了! ,有迷茫出现了! ,有迷茫出现了! ,有迷茫出现了! ,有迷茫出现了!
时刻 8,zy 移动到了位置 移动到了位置 移动到了位置 移动到了位置 4。
时刻 9,zy 移动到了位置 移动到了位置 移动到了位置 移动到了位置 5,迷茫消失。 ,迷茫消失。 ,迷茫消失。
【数据范围】 【数据范围】
对于 30%30%30%的数据 的数据 : N, M, t <= 100t <= 100 t <= 100t <= 100 t <= 100t <= 100
对于 60%60%60%的数据 的数据 : N, M, t <= N, M, t <= N, M, t <= N, M, t <= N, M, t <= N, M, t <= 1000010000100001000010000
对于 100%100%100%100%的数据 的数据 : N, M, t <= 100000 N, M, t <= 100000 N, M, t <= 100000N, M, t <= 100000N, M, t <= 100000 N, M, t <= 100000N, M, t <= 100000N, M, t <= 100000N, M, t <= 100000N, M, t <= 100000N,



  这么长的题面,呵呵了。

  发现如果每次处理一个迷惘,则只有O(N)次操作,考虑将每次的复杂度降为log2N。

  这里用的treap。

  1 #include <algorithm>
  2 #include <iostream>
  3 #include <cstring>
  4 #include <cstdlib>
  5 #include <cstdio>
  6 using namespace std;
  7 const int maxn=200010;
  8 const long long INF=10000000000000000LL;
  9 struct Node{
 10     long long t,a,b;
 11     int id,tp;
 12     Node(long long t_=0,long long a_=0,long long b_=0,int id_=0,int tp_=0){
 13         t=t_;a=a_;b=b_;id=id_;tp=tp_;
 14     }
 15 }px[maxn],t[maxn];
 16
 17 bool cmp(Node x,Node y){
 18     return x.t<y.t;
 19 }
 20
 21 int cnt;
 22 int sz[maxn],rt;
 23 int ch[maxn][2];
 24 void Push_up(int x){
 25     sz[x]=sz[ch[x][0]]+sz[ch[x][1]]+1;
 26 }
 27
 28 int Newnode(Node x){
 29     sz[++cnt]=1;t[cnt]=x;
 30     ch[cnt][0]=ch[cnt][1]=0;
 31     return cnt;
 32 }
 33
 34 int Merge(int x,int y){
 35     if(!x||!y)return x|y;
 36     if(rand()%2){
 37         ch[x][1]=Merge(ch[x][1],y);
 38         Push_up(x);return x;
 39     }
 40     else{
 41         ch[y][0]=Merge(x,ch[y][0]);
 42         Push_up(y);return y;
 43     }
 44 }
 45
 46 int ta,tb;
 47 void Split(int p,long long k){
 48     if(p==0)return;
 49     if(k==sz[ch[p][0]]+1){
 50         ta=ch[p][0];tb=p;
 51         ch[p][0]=0;Push_up(p);
 52         return;
 53     }
 54     if(k<sz[ch[p][0]]+1){
 55         Split(ch[p][0],k);
 56         ch[p][0]=tb;tb=p;
 57         Push_up(p);
 58     }
 59     else{
 60         k-=sz[ch[p][0]]+1;
 61         Split(ch[p][1],k);
 62         ch[p][1]=ta;ta=p;
 63         Push_up(p);
 64     }
 65 }
 66
 67 int tx,ty,tz;
 68 void Get_div(int l,int r){
 69     Split(rt,r+1);ty=ta;tz=tb;
 70     Split(ty,l);tx=ta;ty=tb;
 71 }
 72
 73 void Get_mer(){
 74     tx=Merge(tx,ty);
 75     rt=Merge(tx,tz);
 76 }
 77
 78 int ID,POS;
 79 void Get_Prev(long long k){
 80     int p=rt,num=0;
 81     while(p){
 82         if(t[p].a<=k){
 83             ID=p;num+=sz[ch[p][0]]+1;
 84             POS=num;p=ch[p][1];
 85         }
 86         else p=ch[p][0];
 87     }
 88     return;
 89 }
 90
 91 void Get_Succ(long long k){
 92     int p=rt,num=0;
 93     while(p){
 94         if(t[p].a<k){
 95             num+=sz[ch[p][0]]+1;
 96             p=ch[p][1];
 97         }
 98         else{
 99             ID=p;POS=num+sz[ch[p][0]]+1;
100             p=ch[p][0];
101         }
102     }
103     return;
104 }
105
106 //严格小于x的个数
107 long long Get_Min(long long x){
108     Get_Succ(x);
109     return POS-1;
110 }
111
112 void Insert(Node x){
113     Get_Prev(x.a);
114     Split(rt,POS+1);
115     ta=Merge(ta,Newnode(x));
116     rt=Merge(ta,tb);
117 }
118
119 void Delete(int p){
120     Get_div(p,p);
121     rt=Merge(tx,tz);
122 }
123
124 int n,m;
125 long long nt=0,np=1;
126 int Get_Tow(){
127     long long Min=Get_Min(np);
128     long long Max=sz[rt]-Min;
129     return Min<=Max?1:-1;
130 }
131
132 void Init(){
133     rt=Newnode(Node(0,-1,0,0,0));
134     rt=Merge(rt,Newnode(Node(0,INF,0,0,0)));
135 }
136
137
138 void Print(long long p){
139     if(!p)return;
140     Print(ch[p][0]);
141     printf("%lld ",t[p].a);
142     Print(ch[p][1]);
143 }
144
145 void Debug(){
146     printf("~~~~~~~~~~~~~~~~~\n");
147     Print(rt);
148     printf("\n~~~~~~~~~~~~~~~~~\n");
149 }
150
151
152 long long ans[maxn];
153 int main(){
154     freopen("sm.in","r",stdin);
155     freopen("sm.out","w",stdout);
156     Init();
157     scanf("%d%d",&n,&m);srand(n);
158     for(int i=1;i<=n;i++){
159         long long t,a,b;
160         scanf("%lld%lld%lld",&t,&a,&b);
161         px[i]=Node(t,a,b,i,0);
162     }
163     sort(px+1,px+n+1,cmp);
164     for(int i=1;i<=n;i++){
165         while(sz[rt]>2){
166             int tow=Get_Tow();
167             if(tow==1){
168                 Get_Succ(np);
169                 if(nt+t[ID].a-np>=px[i].t){
170                     np+=px[i].t-nt;
171                     break;
172                 }
173                 nt+=t[ID].a-np;
174                 np=t[ID].a;
175                 Delete(POS);
176                 if(t[ID].tp==0)
177                     Insert(Node(0,t[ID].b,0,t[ID].id,1));
178                 else
179                     ans[t[ID].id]=nt;
180             }
181             else{
182                 Get_Prev(np);
183                 if(nt+np-t[ID].a>=px[i].t){
184                     np-=px[i].t-nt;
185                     break;
186                 }
187                 nt+=np-t[ID].a;
188                 np=t[ID].a;
189                 Delete(POS);
190                 if(t[ID].tp==0)
191                     Insert(Node(0,t[ID].b,0,t[ID].id,1));
192                 else
193                     ans[t[ID].id]=nt;
194             }
195         }
196         Insert(px[i]);
197         nt=px[i].t;
198         //Debug();
199     }
200     while(sz[rt]>2){
201         int tow=Get_Tow();
202         if(tow==1){
203             Get_Succ(np);
204             nt+=t[ID].a-np;
205             np=t[ID].a;
206             Delete(POS);
207             if(t[ID].tp==0)
208                 Insert(Node(0,t[ID].b,0,t[ID].id,1));
209             else
210                 ans[t[ID].id]=nt;
211         }
212         else{
213             Get_Prev(np);
214             nt+=np-t[ID].a;
215             np=t[ID].a;
216             Delete(POS);
217             if(t[ID].tp==0)
218                 Insert(Node(0,t[ID].b,0,t[ID].id,1));
219             else
220                 ans[t[ID].id]=nt;
221         }
222     }
223     for(int i=1;i<=n;i++)
224         printf("%lld\n",ans[i]);
225     return 0;
226 }


第三天

博士的选取器(Selector.cpp)
【题目描述】
浏览到好图好句的时候,为了避免被删帖、封图、和谐,博士会掏出他的选取器,将好图好句框住,然后Ctrl+C,Ctrl+V。博士从初一开始坚持到现在,已经有2GB了。在反复地与吧主斗争之后,博士总结出了经验。
1).对于一篇帖子,可以从上至下分成N个片段,每个片段不可分割,且只有序号相邻的片段才相邻。
2).每次框选只能框选连续一段片段[L,R],而且这连续一段片段的总字符量不能超过LIMIT,否则会出错。
3).对于每次框选与复制,耗时只与这连续一段片段中字符量最大的那一个片段有关,而且满足正比例函数关系。为了让题目简单,规定耗时等于字符量。
4).两次框选之间的时间间隔可以视为0。
正在博士总结完经验的时候,他瞅到了一篇掺杂大量好图好句的帖子。于是,一场新的战争爆发了…………战局紧张,博士想知道他的最小耗时是多少。
【输入】
第一行两个整数N和Limit。
接下来的N行,每行一个整数,代表第I个片段的字符量
【输出】
仅一行,为博士的最小耗时。
【样例】
Sample Input (Selector.in)
Sample Output (Selector.out)
8 17
2
2
2
8
1
8
2
1
12
{解释:222/818/21,2+8+2=12}
【数据范围】
40%的数据N<=1000
100%的数据N<=300000

这个代码被卡常,无力吐槽,比时限长了0.05S左右,TM还是稳定的。

别人再带一个单调栈复杂度的,线段树优化一下照样踩我程序,QAQ……


  1 #include <algorithm>
  2 #include <iostream>
  3 #include <cstring>
  4 #include <cstdio>
  5 using namespace std;
  6 const int maxn=300010;
  7 const long long INF=1000000000000000LL;
  8 int a[maxn];
  9 long long sum[maxn],dp[maxn];
 10 long long tx[maxn*4],ty[maxn*4],tz[maxn*4],tw[maxn*4];
 11
 12 void Push_down(int x){
 13     if(ty[x]==INF)return;
 14     ty[x<<1]=ty[x];
 15     ty[x<<1|1]=ty[x];
 16     tz[x<<1]=tx[x<<1]+ty[x];
 17     tz[x<<1|1]=tx[x<<1|1]+ty[x];
 18     ty[x]=INF;
 19 }
 20
 21 void Push_up(int x){
 22     tx[x]=min(tx[x<<1],tx[x<<1|1]);
 23     tz[x]=min(tz[x<<1],tz[x<<1|1]);
 24 }
 25
 26 void Update(int x,int l,int r,int a,int b,int m){
 27     if(a>b)return;
 28     if(l>=a&&r<=b){
 29         ty[x]=m;
 30         tz[x]=m+tx[x];
 31         return;
 32     }
 33     Push_down(x);
 34     if(l+r>>1>=a)Update(x<<1,l,l+r>>1,a,b,m);
 35     if(l+r>>1<b)Update(x<<1|1,(l+r>>1)+1,r,a,b,m);
 36     Push_up(x);
 37 }
 38
 39 void Insert(int x,int l,int r,int g){
 40     if(l==r){
 41         tx[x]=dp[l];
 42         ty[x]=INF;
 43         return;
 44     }Push_down(x);
 45     if(l+r>>1>=g)Insert(x<<1,l,l+r>>1,g);
 46     else Insert(x<<1|1,(l+r>>1)+1,r,g);
 47     Push_up(x);
 48 }
 49
 50 long long Query(int x,int l,int r,int a,int b){
 51     if(a>b)return INF;
 52     if(l>=a&&r<=b)return tz[x];
 53     Push_down(x);
 54     long long ret=INF;
 55     int mid=(l+r)>>1;
 56     if(mid>=a)
 57         ret=Query(x<<1,l,mid,a,b);
 58     if(mid<b)
 59         ret=min(ret,Query(x<<1|1,mid+1,r,a,b));
 60     return ret;
 61 }
 62
 63 void Insert2(int x,int l,int r,int g){
 64     if(l==r){
 65         tw[x]=a[l];
 66         return;
 67     }
 68     if(l+r>>1>=g)Insert2(x<<1,l,l+r>>1,g);
 69     else Insert2(x<<1|1,(l+r>>1)+1,r,g);
 70     tw[x]=max(tw[x<<1],tw[x<<1|1]);
 71 }
 72
 73 int Q(int x,int l,int r,long long g){
 74     if(l==r)return l;
 75     if(tw[x<<1|1]<g)
 76         return Q(x<<1,l,l+r>>1,g);
 77     else
 78         return Q(x<<1|1,(l+r>>1)+1,r,g);
 79 }
 80 int n,lim;
 81 int main(){
 82     freopen("Selector.in","r",stdin);
 83     freopen("Selector.out","w",stdout);
 84     scanf("%d%d",&n,&lim);
 85     for(int i=1;i<=n;i++){
 86         scanf("%d",&a[i]);
 87         sum[i]=sum[i-1]+a[i];
 88     }
 89     int Max0=0;
 90     memset(tx,63,sizeof(tx));
 91     memset(dp,63,sizeof(dp));
 92     int p=0;
 93     for(int i=1;i<=n;i++){
 94         while(sum[i]-lim>sum[p])p+=1;
 95         if(p==0){
 96             Max0=max(Max0,a[i]);
 97             dp[i]=Max0;p+=1;
 98         }
 99         int q=Q(1,1,n,a[i]);
100         Insert2(1,1,n,i);
101         Update(1,1,n,q,i-1,a[i]);
102         dp[i]=min(dp[i],Query(1,1,n,p,i-1));
103         Insert(1,1,n,i);
104         if(p==1&&sum[i]<=lim)p=0;
105     }
106     printf("%lld\n",dp[n]);
107     return 0;
108 }
时间: 2024-10-05 21:48:11

HNOI 2016 省队集训日记的相关文章

JS省队集训记

不知不觉省队集训已经结束,离noi也越来越近了呢 论考前实战训练的重要性,让我随便总结一下这几天的考试 Day 1 T1 唉,感觉跟xj测试很像啊?meet in middle,不过这种题不多测是什么心态? T2 唉,感觉好像做过类似的? T3 唉,怎么是提交答案题…… 感觉前两题都会,信心大增,于是决定先码T2 码了一会,过了第二个样列,还有一个样例?咦怎么过不去? 纠结了一会发现——读错题了,啪啪啪,全写错了……立马就凌乱了 赶快做T1,结果发现meet in middle的空间复杂度好像炸

【CodeVS 5032】【省队集训2016 Day5 T1】Play with array

一开始我用分块大法,分成$\sqrt{n}$块,每个块上维护一个Splay,然后balabala维护一下,时间复杂度是$O(n\sqrt{n}logn)$.后来对拍的时候发现比$O(n^2)$的暴力跑得还慢,TA爷说是Splay常数太大2333333 标算是块状链表,什么balabala比较基础地维护,卡着空间开2333333 我把块的大小设为$[\frac{\sqrt{n}}{2},\sqrt{n}×2)$,在codevs上TLE,,, 后来把块的大小改成了$[\sqrt{n},\sqrt{n

关于举办第22届全国青少年信息学奥林匹克联赛浙江赛区颁奖大会暨省队集训、选拔的通知

各市科协.教育局,各有关学校: 第22届全国青少年信息学奥林匹克联赛(NOIP2016)成绩已公布,浙江赛区颁奖大会暨集训队首轮培训.选拔将由温州中学和省青少年科技教育协会承办. 我省将根据中国计算机学会<CCF关于2017NOI省内选拔的若干规定>和<浙江省青少年信息学奥林匹克竞赛实施办法>相关规定选拔.组建浙江省队参加于今年暑假期间举行的第34届全国青少年信息学奥林匹克竞赛(NOI2017),参赛名额由全国主办单位规定.现将集训.选拔.颁奖会有关事宜通知如下: 一.集训.选拔对

HNOI 2016 乱做

  4542: [Hnoi2016]大数 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 488  Solved: 182[Submit][Status][Discuss] Description 小 B 有一个很大的数 S,长度达到了 N 位:这个数可以看成是一个串,它可能有前导 0,例如00009312345.小B还有一个素数P.现在,小 B 提出了 M 个询问,每个询问求 S 的一个子串中有多少子串是 P 的倍数(0 也是P 的倍数).例如

集训日记

今天早上脑子不太清醒,突然想到之前教练说的脑子不清醒就该颓博客啊,于是打算开一个日记 记录一下集训期间发生的东西,作为回忆或笑料都好 20190727: 啊-集训开始快10天了才想起来要写日记 早上看着化奥的冲出去跑操莫名开心-导致自己现在还没有睡醒(什么因果关系) 待会要考达哥的题了,滚粗感十分强烈(尽管还没看到题) 总是希望能考好一点,然而次次事与愿违 希望这次能心想事成吧- 我待曙色沾霜,才知南柯一场 原文地址:https://www.cnblogs.com/mikufun-hzoi-cp

FJOI省队集训 florida

省队成员(大部分)都没来...像我这种沙茶天天写写玄学算法都能排在榜上面...果然正解写挂的人远比暴力拍对的人少啊...陆陆续续会补一些题解.(不过有些题太神了可能补不上题解 有n个物品,两个袋子A和B.若物品i与j放在同一个袋子里,那么代价为T[i][j],保证T[i][i]=0,T[i][j]=T[j][i]. 一个袋子的代价D=袋子中两两物品代价的最大值.你需要将物品分配到两个袋子中,最小化D(A)+D(B). 2<=n<=250,0<=T[i][j]<=10^9. 陈旭大爷

[NOIP2017集训日记 2017.9-11]

前言: 这次NOIP好像考不好就退役? 所以写点日记记录生活 好过什么都没留下 给以后做点怀念 2017.9.5 This Problem Is Too Simple! 这个超好的题 只要你想到离散化 O(N2logN) 草过是没有什么毛病的 可是你要想到精益求精 所以这样做不好 其实有O(Nlog N)做法 对于每一种颜色的 影响的是以这个点为端点的一条链 然后对于询问x y可以差分出四条链 我们关键是维护一条链怎么办 发现如果这个点+1了 子树内的肯定也+1 那么就是维护一个树状数组 这个点

湖南省队集训 -- 1

不知道为什么今天状态 大 好 可能是暴力分比较简单吧,来认真写一下总结 开局睡了1h-- 然后考虑a题,发现特殊性:因为最后的和一定是10^n的,最后两个数一定是后面一段全是0,前面一段两个数的和是⑨,0和⑨中间夹一对和为10 然后脑补正解不能,暴力枚举一下好像可以,就是判断是在不好写 然后考虑b题,看N^2算法,脑玩了一下发现距离是不会变得,如果钦定了一个点建站第1~n-1个点产生的权值是不会变得,最后一个点的距离也变不了,唯一得变量需求要乘距离,然后把剩下的不变量加起来,这就是个kx+b的形

HNOI 2016 地图

[题目描述] Hoshizora Rin是个特别好动的少女. 一天Rin来到了一个遥远的都市.这个都市有N个建筑,编号从1到N,其中市中心编号为1,这个都市有M条双向通行的街道,每条街道连接着两个建筑,其中某些街道首尾相连连接成了一个环.Rin通过长时间的走访,已经清楚了这个都市的两个特点: 从市中心出发可以到达所有的建筑物. 任意一条街道最多存在与一个简单环中. 令Rin心花怒放的是,每个建筑物都会有拉面售卖.拉面有很多不同的种类,但对于Rin而言只有油腻程度的不同,因此我们把油腻程度相同的拉