230715校内赛
T1 串
背景
形貌昳丽的西克是風子国王嫡系军队的 general, 同时也兼任風子王国驻绿鸟国的外交官。
西克喜欢在蕉含流群里与其它王国的使者蕉含流, 但前段时间由于说怪话被来自绿鸟国意识形态 不完全的国王驱含逐出境。
西克非常愤怒, 想要说出一句最怪的话, 但他却忙于敢览求社的训练。
于是, 他找到了你, 无上尼特, 想让你帮助解决他的问题。
题目描述
在風子王国, 一句话由
众所周知, 负负得正, 我们定义一句话的一个区间是怪的, 当且仅当其中含有奇数个怪词。
请构造一句符合条件的话, 使得其中怪的区间数量最多。
输入格式
从文件 string.in 中读入数据。
一行两个整数
输出格式
输出到文件 string.out 中。
第一行一个整数
第二行一个长度为
本题使用自定义校验器检验你的答案是否正确, 因此若有多种满足条件的方案, 你只需要输出任 意一种。
样例
输入数据 1
7 2
输出数据 1
16
0 1 0 0 0 1 0
怪的区间有 [1, 2], [1, 3], [1, 4], [1, 5], [2, 2], [2, 3], [2, 4], [2, 5], [3, 6], [3, 7], [4, 6], [4, 7], [5, 6], [5, 7], [6, 6], [6, 7] 共 16 个。
数据规模与约定
对于所有测试点:
每个测试点的具体限制见下表:
测试点 | ||
---|---|---|
1∼2 | ≤n | |
3∼5 | 同上 | |
6∼7 | 1 | |
8 | 同上 | 2 |
9∼10 |
题解
打表题,正常看挺难看出它的规律,打表则很容易计算出来
是我不会推导
有人忘了开longlong,还没特判
大概看了一下正常思路代码我就不写了
先特判
将数组做前缀和, 令前缀和数组中 1 的个数为
#include<bits/stdc++.h>
using namespace std;
int n,k,a[100010];
long long ans;
int main(){
freopen("string.in","r",stdin);
freopen("string.out","w",stdout);
scanf("%d%d",&n,&k);
if(k==0){
puts("0");
for(int i = 1;i<=n;i++)
printf("0 ");
return 0;
}
ans = (long long)((n/2)+1)*(long long)(n/2);
if(n%2==1) ans+=(long long)(n/2)+1;
printf("%lld\n",ans);
for(int i = n;i>=n-k+2;i--) a[i] = 1;
a[(n-k)/2+1] = 1;
for(int i = 1;i<=n;i++)
printf("%d ",a[i]);
return 0;
}
背景
吉娜是一名艺术家, 一名表演艺术家 (performance artist)。
此时正值風子王国建国 114514 周年, 風子国王抵德请来艺术家吉娜设计游行的道路。
吉娜非常重占视这份工作, 但却在喝水的时候被巡逻的抵德训占斥工作不认真, 于是剥占夺了吉 娜的设计权利, 将吉娜贬含为了负责计算道路的信息的计算机。
吉娜心想: “为什么设计的时候不能喝水? ?? 我听歌都可以设计好。”
但终是敢怒占不敢言, 不幸的是, 计算量实在太大, 吉娜怕黑, 必须赶在天黑占之前做完工作。 于是他请来了你, 伟大尼特, 帮助它解决这个问题。
题目描述
给定一个长度为 n 的颜色序列 c 。
再给出 m 个区间, 第 i 个区间为
在接下来的 q 个单位时间内, 第
请对于每一个区间求出, 最早的其中所有颜色都互不相同的时间。
输入格式
从文件 artist.in 中读入数据。
第一行三个正整数
接下来一行
接下来
接下来
输出格式
输出到文件 artist.out 中。
令
请输出
样例
输入数据 1
6 6 5
1 2 1 2 1 2
1 6
5 5
4 5
3 5
2 5
1 5
5 2
4 3
2 1
3 4
1 5
输出数据 1
4
【样例解释 1】
数据规模与约定
对于所有数据, 满足
题解
发现所有区间不相交也不包含, 可以看作一个树形的关系, 一个区间的父亲必须在这个区间之后满足要求, 同时, 所有的叶子节点的区间互不相交, 相当于每个点只会在当前的一个区间中, 每次修改之后查询这个区 间是否合法即可。
查询一个区间是否合法有两种方式:
-
建出树, 相当于一个单点修改, 子树数颜色, 使用 dfsdfs 序, set, 树状数组可以做到
。 -
在原数轴上维护
表示 之前第一个颜色与 相同的点, 则一个区间内部颜色互不相同等价于 , 使用 set 和线段树维护可以做到 。时间复杂度
。
#include<bits/stdc++.h>
#define N 500010
#define mid ((l+r)>>1)
#define lc (p<<1)
#define rc ((p<<1)|1)
using namespace std;
struct node{
int x,y,id;
bool operator<(const node &a)const{
return x==a.x?y>a.y:x<a.x;
}
}stk[N],p[N];
set<node>s;
set<node>::iterator it1;
set<int>st[N];
set<int>::iterator it;
int n,m,q,cnt,tim,X,Y,tp,lf[N],rg[N],rd[N],ans[N],c[N],h[N],ne[N],t[N<<2],lst[N],fa[N],pos[N],pre[N];
void add(int p,int l,int r){
if(l==r){
t[p] = Y;
return ;
}
if(X<=mid) add(lc,l,mid);
else add(rc,mid+1,r);
t[p] = max(t[lc],t[rc]);
}
int ask(int p,int l,int r,int ql,int qr){
if(ql<=l&&qr>=r) return t[p];
int res = 0;
if(ql<=mid) res = max(res,ask(lc,l,mid,ql,qr));
if(qr>mid) res = max(res,ask(rc,mid+1,r,ql,qr));
return res;
}
void build(int p,int l,int r){
if(l==r){
t[p] = lst[l];
return ;
}
build(lc,l,mid);
build(rc,mid+1,r);
t[p] = max(t[lc],t[rc]);
}
void change(int x,int y){
if(ne[x]){
X = ne[x];
Y = lst[x];
add(1,1,n);
}
ne[lst[x]] = ne[x];
lst[ne[x]] = lst[x];
st[c[x]].erase(x);
c[x] = y;
int p = lst[x];
it = st[y].upper_bound(x);
lst[x] = ne[x] = 0;
if(it!=st[y].end()){
X = *it;
ne[x] = X;
Y = x;
add(1,1,n);
}
if(it!=st[y].begin()){
it--;
lst[x] = *it;
}
st[y].insert(x);
lst[ne[x]] = ne[lst[x]] = x;
X = x;
Y = lst[x];
if(p^Y) add(1,1,n);
}
void check(int x){
if(ask(1,1,n,lf[x],rg[x])<lf[x]){
s.erase((node){lf[x],rg[x],x});
ans[x] = tim;
if(fa[x]&&(!(--rd[fa[x]]))){
rd[fa[x]] = -1;
s.insert(p[pos[fa[x]]]);
check(fa[x]);
}
}
}
int main(){
freopen("artist.in","r",stdin);
freopen("artist.out","w",stdout);
scanf("%d%d%d",&n,&m,&q);
for(int i = 1;i<=n;i++)
scanf("%d",&c[i]);
for(int i = 1;i<=m;i++){
lst[i] = pre[c[i]];
ne[pre[c[i]]] = i;
pre[c[i]] = i;
st[c[i]].insert(i);
}
build(1,1,n);
for(int i = 1;i<=m;i++){
scanf("%d%d",&p[i].x,&p[i].y) ;
lf[i] = p[i].x;rg[i] = p[i].y;
ans[i] = m+i;
p[i].id = i;
}
sort(p+1,p+m+1);
for(int i = 1;i<=m;i++){
if(p[i].x==p[i].y||ask(1,1,n,p[i].x,p[i].y)<p[i].x){
ans[p[i].id] = 0;
rd[p[i].id] = -1;
continue;
}
pos[p[i].id] = i;
while(tp&&stk[tp].y<p[i].x) tp--;
fa[p[i].id] = stk[tp].id;
stk[++tp] = p[i];
rd[fa[p[i].id]]++;
}
for(int i = 1;i<=m;i++){
if(!rd[p[i].id])
s.insert(p[i]);
}
for(int i = 1;i<=q;i++){
int x,y;
scanf("%d%d",&x,&y);
tim = i;
change(x,y);
it1 = s.upper_bound((node){x,0,0});
if(it1!=s.begin()){
it1--;
check((*it1).id);
}
}
int res = 0;
for(int i = 1;i<=m;i++)
res^=ans[i];
printf("%d",res);
return 0;
}
T3 黑白树(tree)
背景
一天, 風子国王抵德带着助手尼特以及西可和西克来到一片 dark 含森林探险, 在这里, 它们发 现了
与此同时, 杰哥带着彬概也正好发现了这些阿玮。
与此同时, 抵德也发现了杰哥带着彬彬也正好发现了这些阿玮。
抵德说: “如果这些阿玮给你的话, 那么它们就不是我的了”。
杰哥说: “如果这些阿玮给你的话, 那么它们就不是我的了”。
两边吵得不可开蕉♂,这时,尼特发现,这些阿玮有些非常逊,有一些非常勇♂,于是经过调解, 抵德带走了所有逊的阿玮, 杰哥带走了所有勇含的阿玮。
同时, 尼特发现这
题目描述
给定一棵
定义两个点的距离为两个点最短路径上边的条数, 定义一棵树的价值, 为同色点距离的最大值。 请求出在所有情况下, 树的价值之和, 对
输入格式
从文件 tree.in 中读入数据。
第一行一个正整数
接下来
输出格式
输出到文件 tree.out 中。
输出一行一个数, 表示你的答案, 对
样例
输入数据 1
2
1 2
输出数据 1
2
【样例解释 1】
若两个点颜色相同,同色点距离最大值为 1。
若两个点颜色不同,同色点距离最大值为 0。
输入数据 2
6
1 2
2 3
3 4
4 5
3 6
输出数据 2
224
题解
#include<bits/stdc++.h>
#define N 1000010
#define mod 1000000007
using namespace std;
struct edge{
int v,ne;
}e[N<<1];
int n,s,cnt,ans,pos,sum,h[N],dis[N],c[N],dis1[N],c1[N];
bool vis[N];
void add(int u,int v){
e[++cnt].v = v;
e[cnt].ne = h[u];
h[u] = cnt;
}
int ksm(int x,int y){
int ans = 1;
while(y){
if(y&1) ans = 1ll*ans*x%mod;
x = 1ll*x*x%mod;
y>>=1;
}
return ans;
}
void dfs(int u,int fa,int x){
dis[u] = x;
if(dis[u]>dis[pos]) pos = u;
for(int i = h[u];i;i = e[i].ne){
int v = e[i].v;
if(v!=fa) dfs(v,u,x+1);
}
}
int main(){
freopen("tree.in","r",stdin);
freopen("tree.out","w",stdout);
scanf("%lld",&n);
for(int i = 1;i<n;i++){
int u,v;
scanf("%d%d",&u,&v);
add(u,v);add(v,u);
}
dfs(1,1,0);
int x = pos;
pos = 0;
dfs(x,x,0);
for(int i = 1;i<=n;i++){
if(dis[i]==dis[pos])
sum++;
c[dis[i]]++;
}
for(int i = 1;i<=n;i++){
dis1[i] = dis[i];
c1[i] = c[i];
}
x = pos;
dfs(x,x,0);
memset(c,0,sizeof(c));
for(int i = 1;i<=n;i++){
if(dis[i]==dis[pos])
sum++;
c[dis[i]]++;
}
for(int i = 1;i<=n;i++)
vis[min(dis[i],dis1[i])] = true;
int mx = dis[pos];
sum = ksm(2,n);
s = n+1;
for(int i = mx;~i;i--){
if(vis[i]){
ans = (ans+1ll*sum*i%mod)%mod;
printf("%d",ans);
return 0;
}
s-=c[i];
s-=c1[i];
int tmp = ksm(2,s);
ans = (ans+1ll*i*(sum-tmp+mod)%mod)%mod;
sum = tmp;
}
return 0;
}
T4敢览求(rugby)
题目
题解
写不动了容我偷个懒
这道题根本不是给人写的吧
#include<bits/stdc++.h>
#define N 200010
using namespace std;
struct node{
int x,y;
bool operator <(const node A)const{
return x==A.x?y<A.y:x<A.x;
}
};
int n,K,ls[N],rs[N],a[N],b[N],f[N],cc,tot;
multiset<node>st[N];
multiset<node>::iterator it,it1,it2,it3,it4;
void find(multiset<node>&A,int x){
it1 = A.upper_bound((node){x+1,-1});
}
bool ck(multiset<node>&A,multiset<node>&B){
cc = 0;
for(it = B.begin();it!=B.end();it++){
find(A,(*it).x);
if(it1!=A.begin()){
it1--;
if((*it1).y>=(*it).x) return 1;
it1++;
}
if(it1!=A.end()&&(*it1).x<=(*it).y)return 1;
tot++;
}
return 0;
}
void cg1(multiset<node>&A,multiset<node>&B){
it2 = A.begin();
cc = 0;
for(it = B.begin();it!=B.end();it++){
find(A,(*it).x);
while(it2!=A.end()&&(*it2).y<(*it).x)it3=it2,++it2,A.erase(it3);
if(it1!=A.begin()){
it1--;
int xx = -1;
if((*it1).y>=(*it).x){
xx = min((*it).y,(*it1).y);
A.insert((node){(*it).x,xx});
A.erase(it1);
}
if(~xx&&(*it1).y!=xx) A.insert((node){xx+1,(*it1).y});
}
find(A,(*it).y);
if(it1!=A.begin()){
it1--;
int xx = -1;
if((*it1).x<=(*it).y){
xx = min((*it).y,(*it1).y);
A.insert((node){(*it).x,xx});
}
if(~xx&&(*it1).y!=xx) A.insert((node){xx+1,(*it1).y});
A.erase(it1);
}
it2 = A.upper_bound((node){(*it).y+1,-1});
tot++;
}
while(it2!=A.end()){
it3 = it2;
it2++;
A.erase(it3);
}
}
void cg2(multiset<node>&A,multiset<node>&B){
for(it = B.begin();it!=B.end();it++){
int l = (*it).x,r = (*it).y;
find(A,l);
if(it1!=A.begin()){
it1--;
l = max(l,(*it1).y+1);
it1++;
}
while(it1!=A.end()&&(*it1).y<=r){
it2 = it1;
it1++;
A.erase(it2);
}
if(it1!=A.end()) r = min(r,(*it1).x-1);
if(l<=r) A.insert((node){l,r});
tot++;
}
}
void dfs(int x){
if(!ls[x]) swap(ls[x],rs[x]);
if(ls[x]) dfs(ls[x]);
if(rs[x]) dfs(rs[x]);
if(a[x]>=b[x]){
st[x].insert((node){0,K-a[x]-1});
if(b[x]) st[x].insert((node){K-b[x],K-1});
}else st[x].insert((node){K-b[x],K-a[x]-1});
if(!ls[x]) return;
if(!rs[x]){
if(ck(st[ls[x]],st[x])){
cg1(st[ls[x]],st[x]);
f[x] = f[ls[x]];
}else{
cg2(st[ls[x]],st[x]);
f[x] = f[ls[x]]+1;
}
st[x].swap(st[ls[x]]);
return ;
}
multiset<node>tmp1,tmp2;
if(st[ls[x]].size()<st[rs[x]].size()) swap(ls[x],rs[x]);
if(ck(st[x],st[rs[x]])){
tmp1 = st[rs[x]];
cg1(tmp1,st[x]);
if(ck(tmp1,st[ls[x]])){
cg1(st[ls[x]],tmp1);
st[x].swap(st[ls[x]]);
f[x] = f[ls[x]]+f[rs[x]];
}else{
tmp2 = st[rs[x]];
cg2(tmp2,st[x]);
cg1(st[ls[x]],tmp2);
cg2(st[ls[x]],tmp1);
st[x].swap(st[ls[x]]);
f[x] = f[ls[x]]+f[rs[x]]+1;
}
}else if(ck(st[ls[x]],st[x])||ck(st[ls[x]],st[rs[x]])){
cg2(st[x],st[rs[x]]);
cg1(st[ls[x]],st[x]);
swap(st[x],st[ls[x]]);
f[x] = f[ls[x]]+f[rs[x]]+1;
}else{
cg2(st[ls[x]],st[x]);
cg2(st[ls[x]],st[rs[x]]);
st[x].swap(st[ls[x]]);
f[x] = f[ls[x]]+f[rs[x]]+2;
}
}
int main(){
freopen("rugby.in","r",stdin);
freopen("rugby.out","w",stdout);
scanf("%d%d",&n,&K);
for(int i = 1;i<=n;i++)
scanf("%d%d%d%d",&a[i],&b[i],&ls[i],&rs[i]);
dfs(1);
if((*st[1].begin()).x>0) f[1]++;
printf("%d",f[1]);
return 0;
}
最后一道绝对有点问题,烦请各位指正
梦与现实间挣扎着,所求为何
你可以借走我的文章,但你借不走我的智慧 虽然我是傻逼本文来自博客园,作者:cztq,转载请注明原文链接:https://www.cnblogs.com/cztq/p/17561394.html