秉承ACM团队合作的思想懒,这篇blog只有部分题解,剩余的请前往星感大神Star_Feel的blog食用(表示男神汉克斯更懒不屑于写我们分别代写了下...)

C. Cloud Computing

扫描线搞一搞区间(主席树也OK啊,只是空间玄学,主席树理论空间nlogn实际上开小那么10倍8倍没什么锅啊zzzz),对于权值建立权值线段树,然后记录每个权值出现的次数以及区间权值和,然后在线段树上二分求答案即。

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=,M=;
struct node {
int lc,rc;ll c; ll sum;
} t[M]; int rt[N],cnt;
void add(int &u,int l,int r,int c,int p,int pp) {
if(u==) u=++cnt; t[u].c+=c; t[u].sum+=ll(c)*ll(pp);
if(l==r) return ; int mid=(l+r)/;
if(p<=mid) add(t[u].lc,l,mid,c,p,pp);
else add(t[u].rc,mid+,r,c,p,pp);
}
void Merge(int &u1,int u2) {
if(u1==) { u1=u2; return ; } if(u2==) return ;
t[u1].c+=t[u2].c; t[u1].sum+=t[u2].sum;
Merge(t[u1].lc,t[u2].lc); Merge(t[u1].rc,t[u2].rc);
}
int n,K,ys[];
ll find(int u,int l,int r,int k) {
if(t[u].c<=k) return t[u].sum;
if(l==r) return ll(k)*ll(ys[l]);
int mid=(l+r)/;
if(t[t[u].lc].c>=k) return find(t[u].lc,l,mid,k);
else return t[t[u].lc].sum+find(t[u].rc,mid+,r,k-t[t[u].lc].c);
}
int L[],R[],C[],P[],s[];
struct ls {
int x,id;
} A[];
bool cmp(ls n1,ls n2) { return n1.x<n2.x; }
int main() {
scanf("%d%d",&n,&K);
int m; scanf("%d",&m);
cnt=; memset(rt,,sizeof(rt));
int t=;
for(int i=;i<=m;i++) {
int l,r,c,p; scanf("%d%d%d%d",&L[i],&R[i],&C[i],&P[i]);
A[++t]=(ls){P[i],i};
}
sort(A+,A++t,cmp); int tot=;
for(int i=;i<=t;i++) {
if(A[i].x!=A[i-].x) tot++;
s[A[i].id]=tot; ys[tot]=A[i].x;
}
for(int i=;i<=m;i++) {
add(rt[L[i]],,tot,C[i],s[i],P[i]);
add(rt[R[i]+],,tot,-C[i],s[i],P[i]);
}
for(int i=;i<=n;i++) Merge(rt[i],rt[i-]);
ll ans=;
for(int i=;i<=n;i++) ans+=find(rt[i],,tot,K);
printf("%lld\n",ans);
return ;
}

C. Cloud Computing(主席树by_hanks_o)

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long LL;
LL read()
{
LL x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(''<=ch&&ch<=''){x=x*+ch-'';ch=getchar();}
return x;
}
struct node
{
int l,r,lc,rc;LL c,s;
}tr[];int trlen;
void bt(int l,int r)
{
int now=++trlen;
tr[now].l=l;tr[now].r=r;
tr[now].lc=tr[now].rc=-;
tr[now].c=;tr[now].s=;
if(l<r)
{
int mid=(l+r)/;
tr[now].lc=trlen+;bt(l,mid);
tr[now].rc=trlen+;bt(mid+,r);
}
}
void change(int now,LL p,LL c)
{
if(tr[now].l==tr[now].r)
{
tr[now].c+=c;
tr[now].s=(LL)tr[now].l*tr[now].c;
return ;
} int mid=(tr[now].l+tr[now].r)/;
int lc=tr[now].lc,rc=tr[now].rc; if(p<=mid)change(lc,p,c);
else change(rc,p,c); tr[now].c=tr[lc].c+tr[rc].c;
tr[now].s=tr[lc].s+tr[rc].s;
}
LL findans(int now,LL k)
{
if(tr[now].c<=k)return tr[now].s;
if(tr[now].l==tr[now].r)return k*tr[now].l; int mid=(tr[now].l+tr[now].r)/;
int lc=tr[now].lc,rc=tr[now].rc; if(tr[lc].c>=k)return findans(lc,k);
else return tr[lc].s+findans(rc,k-tr[lc].c);
} struct line
{
int id;LL c,p;
line(){}
line(int ID,LL C,LL P){id=ID;c=C;p=P;}
}li[];int len;
bool cmp(line l1,line l2){return l1.id<l2.id;}
int main()
{
int n,k,m,l,r;LL c,p;
n=read(),k=read(),m=read();
for(int i=;i<=m;i++)
{
l=read(),r=read(),c=read(),p=read();
li[++len]=line(l,c,p);
li[++len]=line(r+,-c,p);
} LL ans=;int tp=;
sort(li+,li+len+,cmp);
trlen=;bt(,);
for(int i=;i<=n;i++)
{
while(tp<=len&&li[tp].id==i)change(,li[tp].p,li[tp].c),tp++;
ans+=findans(,k);
}
printf("%lld\n",ans);
return ;
}

C. Cloud Computing(扫描线)

D. Garbage Disposal

强行贪心,>K的直接就扔了,然后剩下的留到后面扔(直接并到后一天的垃圾里面),但是要判断一下今天剩下的还有没有包含前一天的,有的话只能加一个袋子

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
const int N=;
int a[N];
typedef long long ll;
int main() {
int n,k; scanf("%d%d",&n,&k);
ll ans=;
for(int i=;i<=n;i++) scanf("%d",&a[i]);
int last=;
for(int i=;i<n;i++) {
ans+=a[i]/k;
int now=a[i]%k;
if(a[i]-last>=now) { last=now; a[i+]+=last; }
else { last=; ans++; }
}
ans+=a[n]/k; if(a[n]%k!=) ans++; printf("%lld\n",ans);
return ;
}

D. Garbage Disposal(by_hanks_o)

G. Monsters and Potions

这就是一个O(n^4)的硬模拟,枚举集合点,不断重复枚举每个英雄,O(n)判断是否可达以及修改点权

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std; int p[],h[],dd[],d[];bool v[];
int aslen,as[];
int main()
{
int n,m;
scanf("%d%d",&n,&m);
for(int i=;i<=m;i++)scanf("%d%d",&p[i],&h[i]);
for(int i=;i<=n;i++)scanf("%d",&dd[i]); for(int pos=;pos<=n;pos++)
{
bool bk=true;aslen=;
memset(v,false,sizeof(v));
memcpy(d,dd,sizeof(d));
while(bk==true)
{
bk=false;
for(int i=;i<=m;i++)
{
if(v[i]==true)continue;
if(p[i]>=pos)
{
bool flag=true;
int k=h[i];
for(int j=p[i];j>=pos;j--)
{
k+=d[j];
if(k<){flag=false;break;}
}
if(flag==true)
{
as[++aslen]=i;v[i]=true;bk=true;
for(int j=pos;j<=p[i];j++)d[j]=;
}
}
else
{
bool flag=true;
int k=h[i];
for(int j=p[i];j<=pos;j++)
{
k+=d[j];
if(k<){flag=false;break;}
}
if(flag==true)
{
as[++aslen]=i;v[i]=true;bk=true;
for(int j=p[i];j<=pos;j++)d[j]=;
}
}
}
}
if(aslen==m)
{
printf("%d\n",pos);
for(int i=;i<aslen;i++)printf("%d ",as[i]);
printf("%d\n",as[aslen]);
return ;
}
}
printf("-1\n");
return ;
}

G. Monsters and Potions

I. Privatization of Roads in Berland

这题搞了我一天。。%得头皮发麻(主要是没有官方题解啊qwq而且眼瞎没看到discuss有人发了)

首先,两条相同公司的边肯定是放在一起的,这样才能尽可能的让一个点周围的公司较少

(此处作出贡献对的是这个点只被1个公司的边连向的个数)

这样的话,对于每一条边,会对1个点作出贡献。

考虑对于du[i]<=k的点,它最多接受du[i]的贡献

对于k<du[i]<=2*k的点,我们最多让用k条边每个公司都出现一次,然后多出来的du[i]-k条边和前面的边匹配,那么单独的边的条数就是2*k-du[i]

du[i]>2*k必然无解

网络流一手,st连向边流量为1,边连向它连接的两点流量为1,表示它只能对其中一个点作出贡献,另一个点一定可以找到一条和它同个公司的边。点流向ed流量为最多接受的贡献,通过残余网络,需要判断一下每条边是否都用上了

对于输出方案,通过残余网络我们可以知道每条边选了哪个点,考虑到对于这个点我这条边上的公司是单独的,那另一边就是成对的,就让这条边到另一边去匹配

通过discuss我又了解到一种做法,对于k<du[i]<=2*k的点,我们必须找到至少(k-du[i])*2条边两两属于同一个公司,也就是相当于多重匹配问题?

同样是网络流,st连向边流量为1,边连向它连接的两点流量为1,表示它也是只能用于其中一个点的两两配对,点流向ed流量为(k-du[i])*2

这样的话,你还需要判断是否满流

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<vector>
using namespace std;
int read()
{
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(''<=ch&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
void write(int d)
{
if(d<){putchar('-');d=-d;}
if(d>=)write(d/);
putchar(d%+'');
} int n,m,K;
struct node
{
int x,y,c,next;
}a[];int len,last[];
void ins(int x,int y,int c)
{
len++;
a[len].x=x;a[len].y=y;a[len].c=c;
a[len].next=last[x];last[x]=len; len++;
a[len].x=y;a[len].y=x;a[len].c=;
a[len].next=last[y];last[y]=len;
}
int st,ed,h[],list[];
bool bt_h()
{
int head=,tail=;list[]=st;
memset(h,,sizeof(h));h[st]=;
while(head!=tail)
{
int x=list[head];
for(int k=last[x];k;k=a[k].next)
{
int y=a[k].y;
if(a[k].c>&&h[y]==)
{
h[y]=h[x]+;
list[tail++]=y;
}
}
head++;
}
if(h[ed]==)return false;
return true;
}
int findflow(int x,int f)
{
if(x==ed)return f;
int s=;
for(int k=last[x];k;k=a[k].next)
{
int y=a[k].y;
if(a[k].c>&&h[y]==h[x]+&&s<f)
{
int t=findflow(y,min(a[k].c,f-s));
s+=t;a[k].c-=t;a[k^].c+=t;
}
}
if(s==)h[x]=;
return s;
} //-------------------------------------------dicnic------------------------------------ int u[],v[],du[];
bool check()
{
int c=;
for(int i=,k=;i<=m;i++,k+=)c+=a[k].c;
return c==m;
}
vector<int>vec[];
int as[];
int main()
{
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
int T;
T=read();
while(T--)
{
n=read(),m=read(),K=read();
len=;memset(last,,sizeof(last));
st=n+m+,ed=n+m+;
memset(du,,sizeof(du));
for(int i=;i<=m;i++)
{
u[i]=read(),v[i]=read();
ins(st,i+n,);
du[u[i]]++,du[v[i]]++;
}
for(int i=;i<=m;i++)
ins(i+n,u[i],),ins(i+n,v[i],);
bool flag=false;
for(int i=;i<=n;i++)
{
if(du[i]<=K)ins(i,ed,du[i]);
else if(du[i]<=*K)ins(i,ed,*K-du[i]);
else
{
for(int i=;i<m;i++)putchar(''),putchar(' ');
putchar(''),puts("");
flag=true;break;
}
}
if(flag==true)continue; /*printf("\n");
for(int i=2;i<=len;i+=2)printf("%d %d %d\n",a[i].x,a[i].y,a[i].c);*/
int ans=;
while(bt_h())
{
ans+=findflow(st,(<<));
/*printf("\n");
for(int i=2;i<=len;i+=2)printf("%d %d %d\n",a[i].x,a[i].y,a[i].c);
printf("%d\n",ans);*/
}
if(!check())
{
for(int i=;i<m;i++)putchar(''),putchar(' ');
putchar(''),puts("");
continue;
} for(int i=;i<=n;i++)vec[i].clear();
for(int i=,k=+*m+;i<=m;i++,k+=)
{
if(a[k].c==)vec[u[i]].push_back(i);
else vec[v[i]].push_back(i);
}
int cnt=;
for(int i=;i<=n;i++)
for(int j=;j<vec[i].size();j++)
{
if(j%==)cnt++;
as[vec[i][j]]=cnt;
}
for(int i=;i<m;i++)write(as[i]),putchar(' ');
write(as[m]);puts("");
}
return ;
}

I. Privatization of Roads in Berland

J. Streets and Avenues in Berhattan

考虑一个性质,对于最后不方便度的贡献只会来自于1种字母,否则我们可以通过两个不同字母的行列交换满足这一条件

枚举这一个字母,因为其他的字母都可以全部放满了,对行进行背包,f[k]表示行有k个已经被命名是否可行

假如k可行,剩下的行就有n-k个,因为我们是i这个字母不放,剩下都可以放列,所以剩余列数就是m-(K-c[i]-k)

求剩余行和列乘积的最小值即可

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std; char ss[];
int c[];
bool f[];
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int n,m,K;
scanf("%d%d%d",&n,&m,&K);
scanf("%s",ss+);
memset(c,,sizeof(c));
for(int i=;i<=K;i++)c[ss[i]-'A'+]++; int ans=(<<);
for(int i=;i<=;i++)
{
memset(f,false,sizeof(f));f[]=true;
for(int j=;j<=;j++)
{
if(i==j||c[j]==)continue;
for(int k=n;k>=c[j];k--)f[k]|=f[k-c[j]];
} for(int k=;k<=n;k++)
if(f[k]==true)
{
int h=max(,n-k),l=max(,m-(K-c[i]-k));
if(h+l<=c[i])ans=min(ans,h*l);
}
}
printf("%d\n",ans);
}
return ;
}

J. Streets and Avenues in Berhattan

L. Odd Federalization

一道挺神的题,假如是考场做就只能暴力猜结论了??

结论是一个图拆分成r个诱导子图并且满足每个点的度数都为偶数,r<=2

r=1明显直接做

r=2对于每个点都有0或1两种取值,若一个点度数为偶数,那么要满足条件的话所有它连向的点的权值异或和应该等于0

若为奇数,则所有它连向的点的权值异或和再异或当前点的点权应该等于1

高斯消元解异或方程可踩此题

那么为什么呢,反证它一手

考虑对于高斯消元无解的情况,是出现0=1

右边是1证明产生选出来的这些柿子的点,有奇数个度数为奇数的点

左边是0证明所有参与了运算的点的系数都是偶数,那么也包括上面那奇数个度数为奇数的点,而剩下的点的度数都应该为偶数

用这个算出来,这些点组成的图的度数就是奇数了(偶*偶+奇*奇=奇数),然而对于无向图度数一定是偶数QWQ

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<bitset>
using namespace std; int n,m,du[];
bool check()
{
for(int i=;i<=n;i++)
if(du[i]%==)return false; printf("1\n");
for(int i=;i<n;i++)printf("1 ");
printf("1\n");
return true;
}
bitset<>s[];
void gauss()
{
int x=;
for(int j=;j<=n;j++)
{
for(int i=x;i<=n;i++)
if(s[i][j]==){swap(s[i],s[x]);break;}
if(s[x][j]==)continue; for(int i=;i<=n;i++)
{
if(i==x)continue;
if(s[i][j]==)s[i]^=s[x];
}
x++;
}
}
int as[];
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int x,y;
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++)s[i].reset();
memset(du,,sizeof(du));
for(int i=;i<=m;i++)
{
scanf("%d%d",&x,&y);
du[x]++,du[y]++;
s[x][y]=,s[y][x]=;
}
if(check())continue; for(int i=;i<=n;i++)
if(du[i]%==)s[i][i]=,s[i][n+]=;
gauss();
x=;
for(int j=;j<=n;j++)
{
if(s[x][j]==){as[j]=;continue;}
as[j]=s[x][n+]+;x++;
} printf("2\n");
for(int i=;i<n;i++)printf("%d ",as[i]);
printf("%d\n",as[n]);
}
return ;
}

L. Odd Federalization

codeforce1070 2018-2019 ICPC, NEERC, Southern Subregional Contest (Online Mirror, ACM-ICPC Rules, Teams Preferred) 题解的更多相关文章

  1. 2018.10.20 2018-2019 ICPC,NEERC,Southern Subregional Contest(Online Mirror, ACM-ICPC Rules)

    i207M的“怕不是一个小时就要弃疗的flag”并没有生效,这次居然写到了最后,好评=.= 然而可能是退役前和i207M的最后一场比赛了TAT 不过打得真的好爽啊QAQ 最终结果: 看见那几个罚时没, ...

  2. 2018-2019 ICPC, NEERC, Southern Subregional Contest (Online Mirror, ACM-ICPC Rules, Teams Preferred)

    A. Find a Number 找到一个树,可以被d整除,且数字和为s 记忆化搜索 static class S{ int mod,s; String str; public S(int mod, ...

  3. 2018-2019 ICPC, NEERC, Southern Subregional Contest (Online Mirror) Solution

    从这里开始 题目列表 瞎扯 Problem A Find a Number Problem B Berkomnadzor Problem C Cloud Computing Problem D Gar ...

  4. 2018-2019 ICPC, NEERC, Southern Subregional Contest (Online Mirror, ACM-ICPC Rules, Teams Preferred) Solution

    A. Find a Number Solved By 2017212212083 题意:$找一个最小的n使得n % d == 0 并且 n 的每一位数字加起来之和为s$ 思路: 定义一个二元组$< ...

  5. Codeforces1070 2018-2019 ICPC, NEERC, Southern Subregional Contest (Online Mirror, ACM-ICPC Rules, Teams Preferred)总结

    第一次打ACM比赛,和yyf两个人一起搞事情 感觉被两个学长队暴打的好惨啊 然后我一直做傻子题,yyf一直在切神仙题 然后放一波题解(部分) A. Find a Number LINK 题目大意 给你 ...

  6. 2018-2019 ICPC, NEERC, Southern Subregional Contest

    目录 2018-2019 ICPC, NEERC, Southern Subregional Contest (Codeforces 1070) A.Find a Number(BFS) C.Clou ...

  7. Codeforces 2018-2019 ICPC, NEERC, Southern Subregional Contest

    2018-2019 ICPC, NEERC, Southern Subregional Contest 闲谈: 被操哥和男神带飞的一场ACM,第一把做了这么多题,荣幸成为7题队,虽然比赛的时候频频出锅 ...

  8. 2016-2017 ACM-ICPC, NEERC, Southern Subregional Contest (Online Mirror) in codeforces(codeforces730)

    A.Toda 2 思路:可以有二分来得到最后的数值,然后每次排序去掉最大的两个,或者3个(奇数时). /************************************************ ...

  9. 【*2000】【2018-2019 ICPC, NEERC, Southern Subregional Contest C 】Cloud Computing

    [链接] 我是链接,点我呀:) [题意] [题解] 我们可以很容易知道区间的每个位置有哪些安排可以用. 显然 我们优先用那些花费的钱比较少的租用cpu方案. 但一个方案可供租用的cpu有限. 我们可以 ...

随机推荐

  1. MySQLWorkBench怎么设置主键自增长

    参考 https://blog.csdn.net/qq_40472613/article/details/87858099 勾选AI选项,相当于执行了这个语句: AUTO_INCREMENT表示自增 ...

  2. ARX亮显问题

    转载一段acedSSSetFirst的用法仅供参考:打个比方,我创建了一个命令,这个命令的功能是提示用户选择,然后只过滤文本对象作为选择集,随后在屏幕上使得这个选择集的所有成员都亮显,并且能够显示出各 ...

  3. Redis系列(八)--缓存穿透、雪崩、更新策略

    1.缓存更新策略 1.LRU/LFU/FIFO算法剔除:例如maxmemory-policy 2.超时剔除,过期时间expire,对于一些用户可以容忍延时更新的数据,例如文章简介内容改了几个字 3.主 ...

  4. bazel和TensorFlow安装

    bazel安装:https://docs.bazel.build/versions/master/install-ubuntu.html#install-with-installer-ubuntu 安 ...

  5. python输出带颜色字体详解

    在python开发的过程中,经常会遇到需要打印各种信息.海量的信息堆砌在控制台中,就会导致信息都混在一起,降低了重要信息的可读性.这时候,如果能给重要的信息加上字体颜色,那么就会更加方便用户阅读了. ...

  6. django中配置允许跨域请求

    对于django 安装django-cors-headers,详情请看官方文档 pip install django-cors-headers 配置settings.py文件 a.在INSTALLED ...

  7. mesh topology for airfoil, wing, blade, turbo

    ref Ch. 5, Anderson, CFD the basics with applications numerical grid generation foundations and appl ...

  8. 51nod 1241 特殊的排序

    [题解] 设满足前后两个元素之差为1的最长上升子序列LIS的长度为m,那么本题的答案即为n-m. 证明: 1,n-m次移动一定可以让序列递增.设LIS的第一个数为i,最后一个数为j,我们按照i-1到1 ...

  9. BZOJ 1726 洛谷 2865 [USACO06NOV]路障Roadblocks【次短路】

    ·求1到n的严格次短路. [题解] dijktra魔改?允许多次入队,改了次短路的值也要入队. #include<cstdio> #include<algorithm> #de ...

  10. Spring核心技术(三)——Spring的依赖及其注入(续)

    本文将继续前文,针对依赖注入的细节进行描述 依赖注入细节 如前文所述,开发者可以通过定义Bean的依赖的来引用其他的Bean或者是一些值的,Spring基于XML的配置元数据通过支持一些子元素< ...