JOISC 2020 Day3
T1 Constellation3
原題
CSDN下載:https://download.csdn.net/download/Ljnoit/12262096
鏈接
翻譯
題目描述
JOI 君拍了一張 的星空圖,將左起第 列,下起第 行的像素點稱爲像素 。
畫面裏有白色的大樓,黃色的星星,黑色的空格。第 列從最下方到自下數起第 行都是白色的大樓。有 個星星,第 個星星位於像素點 。此外,所有的像素點都是黑色。
若一個長方形區域可以稱作星座,則滿足以下條件:
- 1.不含白色像素點。
- 2.至少存在兩個星星。
看厭了星座的 JOI 君要把一些黃色的星星塗成黑色,使得沒有星座存在。將第 個星星塗成黑色會使照片的不自然度增加 ,最初不自然度爲 。求不自然度的最小值。
輸入格式
輸入第一行爲一個整數 ,表示地圖的邊長大小。
第二行爲 個整數 ,描述如題目。
第三行爲一個整數 ,表示星星的個數。
接下來的 行,每行三個整數 ,即對第 個星星的描述。
輸出格式
輸出不自然度的最小值。
樣例輸入 1
5
1 3 4 2 3
3
1 5 3
4 3 2
2 4 2
樣例輸出 1
2
樣例解釋 1
可以發現把第三個星刪了之後它就和一號構不成星座,且比刪去一號花費少。
樣例輸入 2
7
5 6 2 3 6 7 6
5
7 7 5
3 3 7
3 7 10
1 7 6
4 7 8
樣例輸出 2
16
樣例解釋 2
刪去三號和四號。
數據範圍
對於 % 的數據,,保證:
- ;
- ;
- ;
- ;
- 。
詳細子任務及附加限制如下表:
子任務編號 | 附加限制 | 分值 |
---|---|---|
1 | 14 | |
2 | 21 | |
3 | 無附加限制 | 65 |
解析
法一:
笛卡爾樹+線段樹合併
對於一個區間[li,ri],找到最高點a[x]。
這個區間只能有一個的點。
暴力就是先建出笛卡爾樹:
設表示裏選的最高點是j的最大和。
轉移有:這裏選一個點,左區間選一個,右區間選一個。
可以一個接一個合併,複雜度。
用線段樹合併優化一下就O()
法二:
笛卡爾樹+樹狀數組+dfs序
考慮把笛卡爾樹建成一個樹形關係。
如果在這裏選了一個,選就相當於覆蓋了到的一個祖先(且)。
可以倍增求出。
問題變爲一棵樹上有若干祖先後代鏈,選出不相交的若干鏈,使權值和最大。
經典問題(不是祖先後代鏈也能做),只需要dfs序+樹狀數組實時維護一個點到根的dp值的和就差不多了。
代碼
#pragma GCC optimize(3,"Ofast","inline")
#pragma G++ optimize(3,"Ofast","inline")
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <vector>
#define R register int
#define re(i,a,b) for(R i=a; i<=b; i++)
#define ms(i,a) memset(a,i,sizeof(a))
#define MAX(a,b) (((a)>(b)) ? (a):(b))
#define MIN(a,b) (((a)<(b)) ? (a):(b))
using namespace std;
typedef long long LL;
typedef pair<int,int> PII;
namespace IO {
#include <cctype>
template <typename T>
inline void read(T &x){
x=0;
char c=0;
T w=0;
while (!isdigit(c)) w|=c=='-',c=getchar();
while (isdigit(c)) x=x*10+(c^48),c=getchar();
if(w) x=-x;
}
template <typename T>
inline void write(T x) {
if(x<0) putchar('-'),x=-x;
if(x<10) putchar(x+'0');
else write(x/10),putchar(x%10+'0');
}
template <typename T>
inline void writeln(T x) {
write(x);
putchar('\n');
}
}
using IO::read;
using IO::write;
using IO::writeln;
const int N=2e5+5;
struct Node {
int f[N];
int getfa(int x) {
return x==f[x] ? x : f[x]=getfa(f[x]);
}
void init(int n) {
for(int i=1; i<=n+1; i++) f[i]=i;
}
void merge(int x,int y) {
int fx=getfa(x),fy=getfa(y);
if(fx!=fy) f[fx]=fy;
}
} f1,f2;
int n,m;
LL a[N],c[N];
vector <int> v[N];
vector <PII> s[N];
inline void add(int x,LL g) {
while(x<=n+1) {
c[x]+=g;
x+=(x&(-x));
}
}
inline LL ask(int x) {
LL ret=0;
while(x) {
ret+=c[x];
x-=(x&(-x));
}
return ret;
}
int main() {
read(n);
f1.init(n);
f2.init(n);
for(int i=1; i<=n; i++) {
read(a[i]);
v[a[i]].push_back(i);
}
read(m);
int x,y,z;
for(int i=1; i<=m; i++) {
read(x); read(y); read(z);
s[y].push_back(make_pair(x,z));
}
LL ans=0;
for(int i=1; i<=n; i++) {
for(auto r:s[i]) {
LL tmp=ask(r.first);
if(r.second>=tmp){
ans+=tmp;
add(f1.getfa(r.first)+1,r.second-tmp);
add(f2.getfa(r.first),-r.second+tmp);
}
else ans+=r.second;
}
for(auto r:v[i]) {
f1.merge(r,r-1);
f2.merge(r,r+1);
}
}
writeln(ans);
return 0;
}
T2 Harvest
原題
CSDN下載:https://download.csdn.net/download/Ljnoit/12262096
鏈接
翻譯
題目描述
IOI 莊園有 個員工, 棵蘋果樹種在湖岸。湖的周長爲 米。
一開始員工 位於從湖的最北端向順時針方向前進 米處,所有 互異。蘋果樹 生長在從湖的最北端向順時針方向前進 米處,所有 互異。
每棵蘋果樹最多長一個蘋果,收穫後 秒會長出一個新的。時刻 時,所有的蘋果樹上都有一個蘋果。員工從時刻 開始從各自的地點以 的速度順時針前進,遇到成熟的蘋果就將其摘下(若到達時剛長出蘋果,也要摘下),摘蘋果的時間忽略不計。
現給出 個詢問,第 次詢問員工 在時刻 結束時一共收穫到幾個蘋果。
輸入格式
輸入第一行爲四個整數 ,意義由題面所示。
第二行爲 個整數 。
第三行爲 個整數 。
第四行爲一個整數 ,即詢問的數量。
接下來的 行,每行兩個整數 。
輸出格式
輸出共 行,第 行輸出一個整數爲第 個問題的答案。
樣例輸入 1
3 2 7 3
1 4 6
0 5
3
1 7
2 3
3 8
樣例輸出 1
2
1
1
樣例解釋 1
在第 1 個時刻,員工 2 從第 2 棵蘋果樹上收穫了蘋果,員工 3 從第 1 棵蘋果樹上收穫了蘋果。
在第 3 個時刻,員工 2 到達了第 1 棵蘋果樹。但是因爲那時樹上沒果子所以沒收穫。
在第 4 個時刻,員工 1 從第 2 棵蘋果樹上收穫了蘋果。
在第 6 個時刻,員工 1 從第 1 棵蘋果樹上收穫了蘋果,員工 3 到達了第 2 棵蘋果樹,但還是因爲那時樹上沒果子所以沒收穫。
在第 8 個時刻,員工 2 從第 2 棵蘋果樹上收穫了蘋果,員工 3 到達了第 1 棵蘋果樹,但再一次因爲那時樹上沒果子所以沒收穫。
到第 7 個時刻爲止,員工 1 收穫了 2 個蘋果,故第一行輸出 2。
樣例輸入 2
5 3 20 6
0 4 8 12 16
2 11 14
9
4 1932
2 93787
1 89
5 98124798
1 2684
1 137598
3 2
3 8375
4 237
樣例輸出 2
146
7035
7
7359360
202
10320
0
628
18
樣例輸入 3
8 15 217 33608
0 12 71 96 111 128 152 206
4 34 42 67 76 81 85 104 110 117 122 148 166 170 212
14
2 223544052420046341
3 86357593875941375
4 892813012303440034
1 517156961659770735
7 415536186438473633
6 322175014520330760
7 557706040951533058
6 640041274241532527
5 286263974600593111
8 349405886653104871
1 987277313830536091
5 989137777159975413
2 50689028127994215
7 445686748471896881
### 樣例輸出 3
33230868503053
3
5
1
123542793648997
8
165811220737767
8
7
1
1
7
7535161012043
132506837660717
數據範圍
對於 100% 的數據,,,,,保證:
- ;
- ;
- ;
- ;
- ;
- ;
- 。
詳細子任務及附加限制如下表:
子任務編號 | 附加限制 | 分值 |
---|---|---|
1 | 5 | |
2 | 20 | |
3 | 無附加限制 | 75 |
解析
方法:基環樹
考慮對每一個點求出fa[i]表示i取了一個果子後,下一個取這個果子的是誰。
因爲每個點一條出邊,所以是個基環內向樹。
再處理一下每個果子第一次被誰吃,然後把每個果子的時間改爲被第一個人吃的時間+到樹根的時間。
用個線段樹合併再查詢一下得到樹上的答案。
接着考慮環上的答案。
先破環爲鏈,記一個前綴和數組s[x]表示從x走到1的答案,設環長是len。
x,y都是環上的點:
假設y子樹裏的一個果子到y的時間是T1,而x處有一個詢問T2。
設
那麼貢獻就是:
代碼
#pragma GCC optimize(3,"Ofast","inline")
#pragma G++ optimize(3,"Ofast","inline")
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <vector>
#define RI register int
#define re(i,a,b) for(RI i=a; i<=b; i++)
#define ms(i,a) memset(a,i,sizeof(a))
#define MAX(a,b) (((a)>(b)) ? (a):(b))
#define MIN(a,b) (((a)<(b)) ? (a):(b))
using namespace std;
typedef long long LL;
typedef pair<int,int> PII;
namespace IO {
#include <cctype>
template <typename T>
inline void read(T &x){
x=0;
char c=0;
T w=0;
while (!isdigit(c)) w|=c=='-',c=getchar();
while (isdigit(c)) x=x*10+(c^48),c=getchar();
if(w) x=-x;
}
template <typename T>
inline void write(T x) {
if(x<0) putchar('-'),x=-x;
if(x<10) putchar(x+'0');
else write(x/10),putchar(x%10+'0');
}
template <typename T>
inline void writeln(T x) {
write(x);
putchar('\n');
}
}
using IO::read;
using IO::write;
using IO::writeln;
const int N=2e5+5;
const LL inf=2e18;
struct Node {
int ch[2];
int sum;
};
class sgt {
public:
Node t[20000000];
int nodecnt;
void init() {
nodecnt=0;
}
int newnode() {
int p=++nodecnt;
t[p].ch[0]=t[p].ch[1]=t[p].sum=0;
return p;
}
void insert(int &p,LL l,LL r,LL pos) {
if(!p) p=newnode();
t[p].sum++;
if(l==r) return;
LL mid=(l+r)>>1;
if(pos<=mid) insert(t[p].ch[0],l,mid,pos);
else insert(t[p].ch[1],mid+1,r,pos);
}
int query(int p,LL l,LL r,LL ql,LL qr) {
if(!p) return 0;
if(ql<=l && r<=qr) return t[p].sum;
LL mid=(l+r)>>1;
int ret=0;
if(ql<=mid) ret=query(t[p].ch[0],l,mid,ql,qr);
if(qr>mid) ret+=query(t[p].ch[1],mid+1,r,ql,qr);
return ret;
}
int merge(int x,int y) {
if(!x || !y) return x|y;
t[x].sum+=t[y].sum;
t[x].ch[0]=merge(t[x].ch[0],t[y].ch[0]);
t[x].ch[1]=merge(t[x].ch[1],t[y].ch[1]);
return x;
}
} T;
vector<int> pt1;
vector<int> stapple[N],t[N];
vector<pair<int,LL> > query[N];
int n,m,L,C,bans,bane;
int a[N],b[N],Q,fa[N],d[N],vis[N],rt[N];
LL dep[N],ans[N];
void dfs(int np) {
vis[np]=1,pt1.push_back(np);
for(int &x:stapple[np]) T.insert(rt[np],0,inf,x+dep[np]);
for(int &x:t[np]) {
if(np==bans && x==bane) continue;
dep[x]=dep[np]+d[x];
dfs(x);
rt[np]=T.merge(rt[np],rt[x]);
}
for(auto &x:query[np])
ans[x.first]=T.query(rt[np],0,2e18,dep[np],dep[np]+x.second);
}
void solve(int p) {
T.init();
int cx=p;
pt1.clear();
while(!vis[cx]) vis[cx]=1,cx=fa[cx];
bans=fa[cx],bane=cx,dfs(cx);
LL totlen=dep[bans]+d[cx];
T.init();
vector<LL> cur;
for(int &x:pt1) for(int &y:stapple[x])
cur.push_back(y+dep[x]+d[cx]+dep[bans]);
sort(cur.begin(),cur.end());
vector<pair<LL,LL> > c2;
for(int i=bans; i; i=fa[i]) {
for(auto &t:query[i])
c2.push_back(make_pair(t.second+totlen+dep[i],t.first));
if(i==bane) break;
}
sort(c2.begin(),c2.end());
LL vl=0;
int R=0;
for(int i=0,j=0; i<(int)c2.size(); i++) {
while(j<(int)cur.size() && cur[j]<=c2[i].first) {
T.insert(R,0,totlen,cur[j]%totlen);
vl+=cur[j]/totlen;
j++;
}
ans[c2[i].second]-=vl;
ans[c2[i].second]+=1LL*(c2[i].first/totlen)*T.query(R,0,totlen,0,c2[i].first%totlen);
ans[c2[i].second]+=1LL*(c2[i].first/totlen-1)*T.query(R,0,totlen,c2[i].first%totlen+1,totlen);
}
}
int main() {
read(n);
read(m);
read(L);
read(C);
for(int i=1; i<=n; i++) {
read(a[i]);
a[i]=L-1-a[i];
}
for(int i=1; i<=m; i++) {
read(b[i]);
b[i]=L-1-b[i];
}
reverse(a+1,a+n+1);
reverse(b+1,b+m+1);
for(int i=1; i<=n; i++) {
int nxt=(a[i]+C)%L;
if(nxt>a[n])fa[i]=1,d[i]=L+a[1]-nxt+C;
else fa[i]=lower_bound(a+1,a+n+1,nxt)-a,d[i]=a[fa[i]]-nxt+C;
}
for(int i=1; i<=m; i++) {
if(b[i]>a[n]) stapple[1].push_back(a[1]+L-b[i]);
else {
int cur=lower_bound(a+1,a+n+1,b[i])-a;
stapple[cur].push_back(a[cur]-b[i]);
}
}
read(Q);
for(int i=1; i<=Q; i++) {
int p;
LL T;
read(p);
read(T);
query[n+1-p].push_back(make_pair(i,T));
}
for(int i=1; i<=n; i++) t[fa[i]].push_back(i);
for(int i=1; i<=n; i++)
if(!vis[i]) solve(i);
for(int i=1; i<=Q; i++) writeln(ans[i]);
return 0;
}
T3 Stray
原題
CSDN下載:https://download.csdn.net/download/Ljnoit/12262096
鏈接
翻譯
題目描述
這是一道通信題。
Anthony 是一隻生活在 JOI 市的螞蟻。JOI 市共有被劃分爲 個町,編號爲 到 。Anthony 居住在 號町。總共有 條路,編號爲 到 。第 條路連接編號爲 和 的町 (),每條路是雙向的。保證不存在兩條連接兩個相同的町的道路,同時每個點可以直接或間接互相到達。
Catherine 是一隻貓,也是 Anthony 的好朋友。她打算遊覽 JOI 市,但是她並不知道關於路的信息,所以經常迷路。於是,Anthony 打算事先在每條道路上都作上標記。標記共有 種,編號爲 到 。
Catherine 現在到達了 JOI 市。當她不在 號町時,她會做如下事情:
- 對於每種標記,她會統計當前所在的町連出去的道路中,除了她上一次走來的道路(若存在)之外,這種標記共出現了多少次。
之後她會選擇一條路去行動。注意除了上一次走來路,她僅能通過路上的標記來分辨其餘的道路。她想盡量快地到達 號町。更準確地說,若起點至 號町最少需要經過 條道路,那麼她希望在經過不超過 條邊後就能到達 號町。
你需要編寫程序模擬 Anthony 擺放路標和 Catherine 探索 JOI 城的過程。
交互細節
你需要提交兩個程序。
第一個程序爲Anthony.cpp
,它會模擬Anthony的擺放過程。需要包含頭文件Anthony.h
。
-
std::vector<int> Mark(int N, int M, int A, int B, std::vector<int> U, std::vector<int> V)
該程序會恰好在開始時調用一次。- 數字 含義同題面。
- 存儲着所有的邊, 表示第i條路連接的街道 。
選手需要返回一個長度爲 的數組 ,第 個元素 代表在第 條道路上的路標編號。
若 長度不爲 ,測評結果爲 “Wrong Answer [1]”。若不滿足 ,測評結果爲 “Wrong Answer [2]”。
第二個程序爲Catherine.cpp
,它會模擬Catherine的探索過程。需要包含頭文件Catherine.h
。
-
void Init(int A, int B)
該程序會恰好在開始時調用一次。- 數字 含義同題面。
-
int Move(std::vector<int> y)
該程序會在每次Catherine到達一個不是0的街道時調用。- y 是一個長度爲A的數組,元素 yj 代表着所有與當前街道相連且不爲她上一次走過的路(若存在)的路上標記 j 的出現次數。
- 你需要返回一個整數 ,表示選擇走的標記。需要滿足 。若不滿足 ,測評結果爲 “Wrong Answer [3]”。若 ,表示Catherine原路返回,此時若Catherine未進行過任何操作,測評結果爲 “Wrong Answer [4]”。若 ,表示 Catherine 選擇一條標記爲 z 的邊經過,此時若 ,測評結果爲 “Wrong Answer [5]”。
注意如果有多條可以選擇的邊,
grader
不一定會隨機選擇一條合法的出現行動。如果 Catherine 未能在 步內到達街道0,測評結果爲 “Wrong Answer [6]”。
注意事項
選手程序可能會運用若干全局變量和子程序。爲了防止多個文件變量重名或子程序重名帶來的編譯錯誤,請將所有全局變量和子程序定義在一個沒有名字的 namespace 裏。
如果在程序裏使用 printf/scanf/cout/cin
,會直接導致Wrong Answer 或者 Runtime Error。
最終測評時會將 Anthony 和 Catherine 的程序獨立編譯,因此不能共享全局變量。
編譯與運行
將grader.cpp
, Anthony.cpp
,Catherine.cpp
,Anthony.h
,Catherine.h
放在同一文件夾下,在終端內運行如下命令
g++ -O2 -o grader grader.cpp Anthony.cpp Catherine.cpp
編譯成功時會得到一個可執行文件grader
。
可執行文件從標準輸入種讀入以下內容:
第一行五個數字 。其中表示起點。
接下來行,每行兩個數字 ,表示一條道路。
可執行文件回想標準輸出流輸出以下內容。
若程序運行時產生錯誤 [1] 至 [5],則會輸出形如 “Wrong Answer [1]” 的錯誤信息。
否則如果未在 N+B 步內到達街道1,輸出 “Wrong Answer; Number of moves > N + B”.
否則按照 “Number of moves = 4” 的格式輸出信息。
數據範圍
- 子任務1 (2分):。
- 子任務2 (2分):。
- 子任務3 (2分):。
- 子任務4 (9分):。
- 子任務5 (5分):。
- 子任務6 (71分):。
- 子任務7 (9分):。
對於所有測試數據,滿足 。
保證圖聯通且無重邊無自環。
時間限制:2s
空間限制:1GB
解析
對於第一類子任務。我們只能走最短路。
考慮求出這張圖的 BFS 樹,顯然,所有邊要麼是連接相鄰兩層的點(異層邊),要麼是連接同層的點(同層邊)。
如果沒有同層邊,那麼我們只要對於每一層的邊做同一種標記,按 0,1,2 循環標記即可。因爲這樣的話,在某一個點上,即使有兩種存在的標記,我們也可以確定哪一個是往上走的。
那麼如果有了同層邊,其實也很簡單,只要做它下面的那一層的邊的標記即可。
這樣我們依舊可以確定哪一條邊是向上的。
對於第二類子任務,只有兩種標記,但圖是一個樹,而且允許多走六步。
我們先考慮把樹劃分爲若干條鏈,如果一個點有至少兩個兒子,那麼稱之爲分叉點。我們希望標記能夠滿足:
對於每個分叉點,到父親的邊和到兒子的邊的標記不同。
每一條鏈上都是 110010 的循環位移。
那麼對於代碼 B,它先走三步,如果中途走到非鏈的部分就直接確定了方向。否則,它還在鏈上,而且可以確定周圍長度爲 5 的子串的樣子,這樣的話,一定可以確定它是在往上走還是往下走,這樣也確定了方向,而且最多多走 6 步。
代碼
Anthony.cpp:
#include "Anthony.h"
#include <bits/stdc++.h>
using namespace std;
vector<int> Mark(int n,int m,int A,int B,vector<int> U,vector<int> V) {
vector<int> dist(n, -1);
vector<vector<int> > G(n);
for (int i=0; i<m; i++) {
G[U[i]].push_back(V[i]);
G[V[i]].push_back(U[i]);
}
dist[0]=0;
queue<int> que;
que.push(0);
while(!que.empty()) {
int u=que.front();
que.pop();
for(int v:G[u]) {
if(dist[v]==-1) {
dist[v]=dist[u] + 1;
que.push(v);
}
}
}
vector<int> ret(m);
if(A>=3) {
for(int i=0; i<m; i++) {
ret[i]=min(dist[U[i]],dist[V[i]])%3;
}
} else {
const int arr[6]={1,1,0,0,1,0};
for (int i=0; i<n; i++) G[i].clear();
for (int i=0; i<m; i++) {
if(dist[U[i]]>dist[V[i]]) swap(U[i], V[i]);
G[U[i]].push_back(i);
}
function<void(int, int)> dfs=[&](int u,int fr) {
if((int)G[u].size() == 1) {
int p;
if(fr==-1 || ret[fr]==0) {
p = 0;
} else {
p = 2;
}
while((int)G[u].size()==1) {
int i=G[u][0];
int v=V[i];
u=v;
fr=i;
ret[fr]=arr[p];
p=(p+1)%6;
}
}
int c=(fr==-1 ? 1 : ret[fr]^1);
for (int i:G[u]) {
int v=V[i];
ret[i]=c;
dfs(v,i);
}
};
dfs(0,-1);
}
return ret;
}
Catherine.cpp:
#include "Catherine.h"
#include <bits/stdc++.h>
using namespace std;
namespace {
const int arr[6]={1,1,0,0,1,0};
int A,on,fir,last;
vector<int> vec;
vector<int> cs;
inline bool bad(vector<int> v) {
vector<int> al;
for(int i=0; i<6; i++) al.push_back(arr[i]);
for(int i=0; i<6; i++) al.push_back(arr[i]);
for(int i=0; i<8; i++) {
int flag=1;
for(int j=0; j<5; j++) if(al[i+j]!=v[j]) {
flag=0;
break;
}
if(flag) return true;
}
return false;
}
}
void Init(int _A, int B) {
A=_A;
on=0;
fir=1;
last=-1;
}
int Move(vector<int> y) {
if(A>=3) {
int cc=0;
for(int i=0; i<3; i++) cc+=(y[i]!=0 ? 1 : 0);
if(cc==1) {
if(y[0]) return 0;
else if(y[1]) return 1;
else return 2;
} else {
if(y[0] && y[1]) return 0;
else if(y[1] && y[2]) return 1;
else return 2;
}
} else {
if(on) {
if(y[0]==1 && y[1]!=1) return last=0;
else if(y[0]!=1 && y[1]==1) return last=1;
else return last^=1;
}
if(fir) {
fir=0;
if(y[0]!=1 && y[1]!=1) {
if(y[0]) last = 0;
else last = 1;
y[last]--;
cs=y;
vec.push_back(last);
return last;
}
if(y[0]==1) last=0;
else last = 1;
if(y[last^1]!=1) {
on=1;
return last;
}
y[last]--;
cs=y;
vec.push_back(last);
return last;
}
if(y[0]!=1 && y[1]!=1) {
on=1;
return -1;
}
if(y[0]==1 && y[1]==1) {
on=1;
return last^=1;
}
if(y[0]>1) {
on=1;
return last=1;
}
if(y[1] >1) {
on=1;
return last=0;
}
if(vec.size()<3) {
if(y[0]) last=0;
else last=1;
vec.push_back(last);
return last;
}
vector<int> v;
v.push_back(cs[0] ? 0 : 1);
for(int i=0; i<3; i++) {
v.push_back(vec[i]);
}
v.push_back(y[0] ? 0 : 1);
on=1;
if(bad(v)) {
return -1;
} else {
return last=v.back();
}
}
}