【CF】Codeforces Round #539 (Div. 1)
紫名啦!开心owo
开学啦!不开心quq.
以后能写题解都都写div1啦(当然掉下去就orz了)
传送门
A
有一个数列,找出多少个(l,r)使得r−l+1是偶数并且$ a_l * a_{l+1} * a_{l+2} \dots* a_{mid} == a_{mid+1} * a_{mid+2} * \dots * a_r $
发现可以转化为异或前缀和AR 与AL-1相同。扫一遍边加答案边砸进数组里。
\#include<cstdio>
#include<algorithm>
#include<cmath>
#include<iostream>
#include<cstring>
#include<queue>
#include<stack>
#include<vector>
using namespace std;
typedef long long ll;
int n;
int JS[1<<20],OS[1<<20];
main() {
cin>>n;
int now = 0;
OS[0]++;
ll ans = 0;
for(int i=1;i<=n;i++) {
int x; cin>>x;
now^=x;
if(i&1) ans += JS[now],JS[now]++;
else ans += OS[now],OS[now]++;
}
cout<<ans;
}
B
给出一个回文串,可以将该回文串切成若干段再任意拼接
使得拼接之后的串也是回文串并且不是原串
求最小的切割次数
先看他能不能一次切完,然后看两次。这个还要根据长度是奇是偶来看,就是一堆特判,很容易一不小心写挂,就是要思路清晰点就好。
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<iostream>
#include<cstring>
#include<queue>
#include<stack>
#include<vector>
using namespace std;
char ss[5005];
int n;
char so[5005];
bool hw() {
bool fk = 1;
for(int i=1;i<=n;i++) {
if(so[i]!=ss[i]) {
fk = 0; break;
}
}
if(fk) return 0;
int l = n/2,r;
if(n&1) r = l+2; else r = l+1;
while(233) {
if(l==0) return 1;
if(so[l]!=so[r]) break;
l--; r++;
}
return 0;
}
bool orz() {
int st = 0;
for(int i=2;i<=n;i++) {
st = 0;
for(int j=i;j<=n;j++) so[++st] = ss[j];
for(int j=1;j<i;j++) so[++st] = ss[j];
if(hw()) return 1;
}
return 0;
}
bool wori() {
bool fk = 1;
for(int i=1;i<=n;i++) {
if(i==n/2+1) continue;
if(ss[i]!=ss[1]) {
fk = 0; break;
}
}
return fk;
}
int main() {
scanf("%s",&ss[1]);
n = strlen(ss+1);
bool fk = 1;
for(int i=2;i<=n;i++) {
if(ss[i]!=ss[i-1]) {
fk = 0; break;
}
}
if(fk) {
puts("Impossible");
return 0;
}
if(n&1) {
if(orz()) puts("1");
else if(wori()) puts("Impossible");
else puts("2");
} else {
if(ss[n/2]!=ss[1]) { puts("1"); return 0; }
if(orz()) puts("1");
else puts("2");
}
}
C 补
q = 1e5次操作
l ,r 1e9
有一个盆,盆内有水,盆内水为0时,结束。有一个水龙头,根据时间变化流量,初始任何时间流量都为0
操作1:修改某个时间点t,使得如果经过该时间点,水流变为v。(保证如果之前这里有1不会再次覆盖)
操作2:删除某个修改1,保证存在。
操作3:模拟时间点l,r之间,给定水盆初始水流。如果l到r之间没有时间点结束,puts("-1"),否则给出时间(eps = 1e-6)
写一棵splay维护序列,初始在两头放(t=0,s=0) , (t=1e9+1,s=0)的两个虚点,每个splay本身维护(t,s)时间和水速度,维护子树(TL,TR,mn,res,spr)表示子树中最小时间和最大时间,从l到r模拟水流时最小的减少量时刻的减少量,从l到r模拟流水之后水的变化量(带符号),最靠后的那个时间的水速度。
之后就靠自己的数据结构功底了orz,考场上直接码出还不FST的大佬orz orz orz
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#define int long long
#define zig(x) zigzag(x,1)
#define zag(x) zigzag(x,2)
using namespace std;
typedef double db;
const db eps = 1e-6;
const int maxn = 2e5+5;
int q;
struct mat{
int tl,tr,spr;
int re,mn;
};
struct node{
int ls,rs,fa;
int sp,tim;
mat a;
}z[maxn];
int tot,rt;
mat operator+(mat aa,mat bb) {
mat tmp;
tmp.tl = aa.tl; tmp.tr = bb.tr;
tmp.spr = bb.spr;
tmp.re = aa.re + bb.re + (bb.tl - aa.tr) * aa.spr;
tmp.mn = min(aa.mn,aa.re + bb.mn + (bb.tl-aa.tr)*aa.spr);
return tmp;
}
void upd(int x) {
z[x].a.tl = z[x].a.tr = z[x].tim; z[x].a.spr = z[x].sp;
z[x].a.re = z[x].a.mn = 0;
if(z[x].ls) z[x].a = z[z[x].ls].a + z[x].a;
if(z[x].rs) z[x].a = z[x].a + z[z[x].rs].a;
}
void zigzag(int x,int knd) {
int y = z[x].fa;
int o = z[y].fa;
if(o) {
if(z[o].ls==y) z[o].ls = x;
else z[o].rs = x;
}
z[x].fa = o; z[y].fa = x;
if(knd==1) {
z[y].ls = z[x].rs;
z[z[y].ls].fa = y;
z[x].rs = y;
} else {
z[y].rs = z[x].ls;
z[z[y].rs].fa = y;
z[x].ls = y;
}
upd(y); upd(x);
}
void splay(int x,int zx) {
int y,o;
while(z[x].fa!=zx) {
y = z[x].fa; o = z[y].fa;
if(o==zx) {
if(z[y].ls==x) zig(x);
else zag(x);
} else {
if(z[o].ls==y) {
if(z[y].ls==x) zig(y),zig(x);
else zag(x),zig(x);
} else {
if(z[y].rs==x) zag(y),zag(x);
else zig(x),zag(x);
}
}
}
if(!zx) rt = x;
}
void insert(int t,int s) {
++tot; z[tot].tim = t; z[tot].sp = z[tot].a.spr = s;
z[tot].a.tl = z[tot].a.tr = t;
int p = rt;
while(233) {
if(t<z[p].tim) {
if(z[p].ls) p = z[p].ls;
else { z[p].ls = tot; break; }
}
else {
if(z[p].rs) p = z[p].rs;
else { z[p].rs = tot; break; }
}
}
z[tot].fa = p;
splay(tot,0);
}
int houj(int t) { // >= t
int p = rt;
while(233) {
if(t==z[p].tim) break;
if(t<z[p].tim) {
if(z[p].ls&&z[z[p].ls].a.tr>=t) p = z[p].ls;
else break;
} else p = z[p].rs;
}
return p;
}
int qianq(int t) { // <= t
int p = rt;
while(233) {
if(t==z[p].tim) break;
if(t>z[p].tim) {
if(z[p].rs&&z[z[p].rs].a.tl<=t) p = z[p].rs;
else break;
} else p = z[p].ls;
}
return p;
}
int getr(int p) {
while(z[p].rs) p = z[p].rs;
return p;
}
void del(int t) {
int p = houj(t);
splay(p,0);
if(!z[p].ls) { z[z[p].rs].fa = 0; rt = z[p].rs; return; }
int o = getr(z[p].ls);
splay(o,p);
rt = o; z[o].rs = z[p].rs; z[o].fa = 0; z[z[o].rs].fa = o;
upd(o);
return;
}
void init() {
rt = 1;
++tot; z[1].rs = 2;
z[1].sp = 0; z[1].tim = 0; z[1].a.tl = 0; z[1].a.tr = 1e9+1;
++tot; z[2].fa = 1;
z[2].sp = 0; z[2].tim = 1e9+1; z[2].a.tl = z[2].a.tr = 1e9+1;
}
void query(int l,int r,int v) {
if(v==0) {
printf("%I64d\n",l);
return;
}
// int pr = qianq(r); int pl = houj(l);
// if(z[pr].tim<z[pl].tim) {
// printf("-1\n");
// return;
// } else if(pr==pl) {
// int titi = r - z[pl].tim;
// if(1ll*titi*z[pl].sp+v>0) {
// puts("-1"); return;
// }
// db to = v/z[pl].sp;
// printf("%.10lf\n",1.0*l+to);
// }
// db res = (db)v;
int pr = houj(r+1); int pl = qianq(l-1);
splay(pr,0); splay(pl,pr);
int p = z[pl].rs;
int res = v;
if((!p)|| ( res+z[p].a.mn>0 && res + z[p].a.re + z[p].a.spr*(r-z[p].a.tr)>0) ) { puts("-1"); return; }
while(233) {
if(z[p].ls&& ( ( (z[z[p].ls].a.mn + res)<=0 ) || ( z[z[p].ls].a.re + res + z[z[p].ls].a.spr * (z[p].tim-z[z[p].ls].a.tr) <=0) ) ) p = z[p].ls;
else {
if(z[p].ls) res += z[z[p].ls].a.re + z[z[p].ls].a.spr * (z[p].tim-z[z[p].ls].a.tr);
if(z[p].rs&& ( res + z[p].sp * (z[z[p].rs].a.tl-z[p].tim) > 0 ) ) {
res += z[p].sp * (z[z[p].rs].a.tl-z[p].tim);
p = z[p].rs;
} else {
db to = 1.0*res/(-z[p].sp);
printf("%.10lf\n",z[p].tim+to);
break;
}
}
}
return;
}
main() {
scanf("%I64d",&q);
int opt,t,s,l,r,v;
init();
for(int i=1;i<=q;i++) {
scanf("%I64d",&opt);
if(opt==1) {
scanf("%I64d%I64d",&t,&s);
insert(t,s);
} else if(opt==2) {
scanf("%I64d",&t);
del(t);
} else {
scanf("%I64d%I64d%I64d",&l,&r,&v);
//if(q==10000)printf("%I64d %I64d %I64d\n",l,r,v);
query(l,r,v);
}
}
}
D 补
详见