T1 : 序列

    题意:

       一共有T组数据,每组数据有两个长度为n的序列a,b,m个操作,问a序列是否可以转换成b,是输出YES,否的话输出NO。

       m个操作分别为ti,xi,yi,若t为1,则x和y上的数可同时加减一;若t为2,则x上的数加一同时y上的数减一,或y上的数加一同时x上的数减一;

        

      大概理解为: 将a上的所有数变成b上的对应的数,当t=1时可以将a[x],a[y]同时加任何数,当t=2时可以将a[x]加任何数同时a[y]上的数减上相同的数(相当于把a[x]一部分值转到a[y]上);

       列:   a : 1 3 5 4     t=1,x=1,y=2         则若a[1] (1) 要加上3,a[2] (3) 也必须加上3,a 变成 4 6 5 4

                 t=2,x=1,y=2    则若a[1] (1) 要加上3,a[2] (3) 必须减去3,a变成 4 0 5 4;    

    数据范围:

         1≤T≤10,1≤n,m≤105,1≤ai,bi≤109


          

    分析:

        这题可以用图论来做

        先定义一个序列 c ,c[i]=a[i]-b[i],这样我们只要判断c中的每一个值是否可以变为零就行了。

        然后读入m个操作

        先不用管t为1时的情况,若 t 为2的话,把 x 和 y 之间连一条无向边,然后将图中的联通块缩点。

        因为联通块中的任何俩个数都可以将他们的一部分值互相转换,所以可以将他们看做一个点,该点的权值就是联通块中的每一个c[i]的和。

        下面记 i 点所在的联通块为bel[i]。

        接下来再操作将t为1时的情况, 将bel[x]与bel[y]之间连一条无向边,若bel[x]=bel[y]则用一个bool数组表示bel[x]有自环,有自环后bel[x]的值就可以成2的倍数增长。

        接下来就对新图进行缩点,可以发现,若两个点之间的路径长度为偶数时,两个点间可进行值的转移。

        所以我们再将图进行黑白染色,同色点之间一定长度为偶数的路径,那么我们就将颜色相同的点进行缩点。

        缩到最后,我们再将判断一下每个联通块是否可以将其的总权值变为零,如果有一个联通块不能将其总权值变为零,则输出NO,反之输出YES。

        我们再看看如何判断联通块之间是否可以将其总权值变为零。

        因为缩点缩到最后一定每个联通块最多只有两个点(黑点和白点),所以判断一下这两个点可不可以变为零就行了。

        只要两个点的权值相同,那么就可以两个点同时加减变为零。

        如果不相等,如果两个点其中一个有自环,且两个点权值差为偶数,那就可以将两个点的值变相同,之后再进行操作。

        因为我们只需要判断联通块是否可以变成零就行了,所以不用建新图,dfs一下就行。

        (我还是太弱了,考场上不会写图,只会n≤2的)


    代码如下:

 #include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector> using namespace std; typedef long long LL; const int N=; LL sum[N];
int bel[N],a[N],color[N];
bool book[N]; vector<int> h[N],g[N]; struct Node
{
int x,y;
}w[N]; void dfs1(int u,int c)//第一次缩点 (t为2时的边)
{
bel[u]=c;
sum[c]+=a[u];
for(int i=;i<g[u].size();i++)
{
int j=g[u][i];
if(!bel[j])
dfs1(j,c);
}
} bool dfs2(int u,int col,bool &pd,LL &suma,LL &sumb)//第二次缩点
{
if(~color[u]) return color[u]==col;//若颜色不一样说明有奇数环 color[u]=col;//进行染色
pd|=book[u];//判断有没有自环 if(col==) suma+=sum[u];//将相同色的点权值相加
else sumb+=sum[u]; bool t=true; for(int i=;i<h[u].size();i++)
{
int j=h[u][i]; t&=dfs2(j,col^,pd,suma,sumb);
} return t;
} int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int n,m;
int cnt_all=,cnt=; scanf("%d%d",&n,&m); for(int i=;i<=n;i++) scanf("%d",&a[i]); for(int i=;i<=n;i++)
{
int x;
scanf("%d",&x);
a[i]=x-a[i]; g[i].clear();//将边初始化
h[i].clear();
} memset(w,,sizeof(w)); while(m--)
{
int p,x,y; scanf("%d%d%d",&p,&x,&y); if(p==)
{
w[cnt_all++]={x,y};//存储当t为1时的边
}
else
{
g[x].push_back(y),g[y].push_back(x);//t为2时将x与y之间连边
}
} memset(sum,,sizeof(sum));//联通块总权值初始化
memset(bel,,sizeof(bel));//每个点属于的联通块 for(int i=;i<=n;i++)
{
if(!bel[i]) dfs1(i,++cnt);
} memset(book,,sizeof(book)); for(int i=;i<cnt_all;i++)
{
int x=bel[w[i].x],y=bel[w[i].y]; if(x==y) book[x]=true;//判断自环
else
{
h[x].push_back(y);//不是自环则加边
h[y].push_back(x);
}
} bool ans=; memset(color,-,sizeof(color));//初始化颜色 for(int i=;i<=cnt;i++)
{
if(color[i]==-)//若没被染过色
{
bool pd=false;//判断自环
LL suma=,sumb=;//黑色和白色点的权值总和 if(dfs2(i,,pd,suma,sumb))
{
if(pd) ans&=(suma+sumb)%==;//判断联通块权值是否可以变为零
else ans&=suma==sumb;
}
else
{
ans&=(suma+sumb)%==;
}
}
} if(ans) puts("YES");
else puts("NO");
}
}

  T2 :

        不会 ~


  T3 : 最小环

      题意:

          给定一个长度为 n 的正整数序列 ai,下标从 1 开始编号。

          我们将该序列视为一个首尾相邻的环。

          更具体地,对于 下标为 i, j(i⩽j) 的两个数 ai​, aj,它们的距离为 min⁡(j−i,i+n−j)。

          现在再给定 m 个整数 k1, k2,..., km。

          对每个 ki​(i=1, 2,..., m),你需要将上面的序列 ai 重新排列,使得环上任意两个距离为 ki 的数字的乘积之和最大。

        大概理解为:给一串数,让你将这串数重新排列,使任意两个中间间隔k-1个数的数的乘积之和最大(数列是头尾相连的)。


   分析:

          根据样例数据推断出,将最大的数两旁放次大的及第二大的,再将次大的数旁放第三大的,以此类推,最后的结果一定是最大的情况。

          总的来说,每次将未放到环中最大的数放入到环中最大的数旁,可使环的结果最大。

          我们只需要将最大的几个数放入一个环中,再将环中最大的几个数放在一起,总结果就最大了。

          接下来,我们就将当k为0~n/2的情况预处理一下,最后询问时直接输出答案就行。

          然后得算一下距离k与分成多少个环的关系。假设一个环中有些个数,那么 (x*k) mod n=0,所以x=gcd(n,k)。

          (我没想到环的个数是用最大公约数求,只搞了k为一的)


   代码如下:

 #include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std; const int N=; long long a[N],f[N]; bool com(int a,int b)
{
return a>b;
} int gcd(int a,int b)//求最大公约数
{
return b ? gcd(b,a%b) : a;
} int main()
{
int n,m;
scanf("%d%d",&n,&m); for(int i=;i<=n;i++) scanf("%d",&a[i]); sort(a+,a+n+,com);//将数从大到小排序 找最大值好用 for(int i=;i<=n;i++)//处理k为零的情况
{
f[]+=a[i]*a[i];
} for(int k=;k<=n/;k++)
{
int t=gcd(n,k),num=n/t;//t为能分成多少个环 num为一个环有多少个数 if(f[t]) continue; for(int i=;i<=n;i++)//依次枚举最大数放入环中
{
if(i%num==)//如果这是上一个环的最后一个数 就加上下一个环
{
f[t]+=a[i+]*a[i+];
continue;
} if((i+)%num==)//如果这是环的倒数第二个数
{
f[t]+=a[i]*a[i+];
}
else f[t]+=a[i]*a[i+];//正常情况下
} }
while(m--)
{
int k;
scanf("%d",&k); if(!k) printf("%lld\n",f[]);//特判当k为零的情况
else
{
k=gcd(n,k);
printf("%lld\n",f[k]);
}
}
}

NOIp ( on line ) 提高组 2020 总结的更多相关文章

  1. Codevs 1069 关押罪犯 2010年NOIP全国联赛提高组

    1069 关押罪犯 2010年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description S 城现有两座监狱,一共 ...

  2. Codevs 1218 疫情控制 2012年NOIP全国联赛提高组

    1218 疫情控制 2012年NOIP全国联赛提高组 时间限制: 2 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description H 国有 n 个城市,这 ...

  3. Codevs 3289 花匠 2013年NOIP全国联赛提高组

    3289 花匠 2013年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description 花匠栋栋种了一排花,每株花都 ...

  4. Codevs 1173 最优贸易 2009年NOIP全国联赛提高组

    1173 最优贸易 2009年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description [问题描述] C 国有n ...

  5. Codevs 3731 寻找道路 2014年 NOIP全国联赛提高组

    3731 寻找道路 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题目描述 Description 在有向图G中,每条边的长度均为1,现给定起点和终点,请你在图中找 ...

  6. Codevs 1138 聪明的质监员 2011年NOIP全国联赛提高组

    1138 聪明的质监员 2011年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题目描述 Description 小 T 是一名质量监督员, ...

  7. Codevs 1217 借教室 2012年NOIP全国联赛提高组

    1217 借教室 2012年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description 在大学期间,经常需要租借教 ...

  8. Codevs 1064 虫食算 2004年NOIP全国联赛提高组

    1064 虫食算 2004年NOIP全国联赛提高组 时间限制: 2 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description 所谓虫食算,就是原先的算式 ...

  9. Codevs 1198 国王游戏 2012年NOIP全国联赛提高组

    1198 国王游戏 2012年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description 恰逢 H 国国庆,国王邀 ...

随机推荐

  1. Java实现 LeetCode 73 矩阵置零

    73. 矩阵置零 给定一个 m x n 的矩阵,如果一个元素为 0,则将其所在行和列的所有元素都设为 0.请使用原地算法. 示例 1: 输入: [ [1,1,1], [1,0,1], [1,1,1] ...

  2. Java中System的详细用法

    System.arraycopy System.arraycopy的函数原型是: public static void arraycopy(Object src, int srcPos, Object ...

  3. Java实现 洛谷 P1208 [USACO1.3]混合牛奶 Mixing Milk

    输入输出样例 输入 #1 100 5 5 20 9 40 3 10 8 80 6 30 输出 #1 630 import java.util.Arrays; import java.util.Scan ...

  4. java实现 蓝桥杯 算法提高 Problem S4: Interesting Numbers 加强版

    1 问题描述 Problem Description We call a number interesting, if and only if: 1. Its digits consists of o ...

  5. java实现基因牛的繁殖

    基因牛的繁殖 基因牛 张教授采用基因干预技术成功培养出一头母牛,三年后,这头母牛每年会生出1头母牛, 生出来的母牛三年后,又可以每年生出一头母牛.如此循环下去,请问张教授n年后有多少头母牛? 以下程序 ...

  6. Java实现除去次方数

    ** 除去次方数** 自然数的平方数是:1 4 9 16 25 - 自然数的立方数是:1 8 27 64 125 - 自然数的4次方数是:1 16 81 256 - - 这些数字都可以称为次方数. 1 ...

  7. java代码(15) ---java8 Function 、Consumer 、Supplier

    Java8 Function.Consumer.Supplier 有关JDK8新特性之前还有三篇博客: 1,java代码(1)---Java8 Lambda 2,java代码(2)---Java8 S ...

  8. 性能调优必备利器之 JMH

    if 快还是 switch 快?HashMap 的初始化 size 要不要指定,指定之后性能可以提高多少?各种序列化方法哪个耗时更短? 无论出自何种原因需要进行性能评估,量化指标总是必要的. 在大部分 ...

  9. vue2.0 + Element UI + axios实现表格分页

    注:本文分页组件用原生 html + css 实现,element-ui里有专门的分页组件可以不用自己写,详情见另一篇博客:https://www.cnblogs.com/zdd2017/p/1115 ...

  10. 伪造随机的User-Agent

    写好爬虫的原则只有一条: 就是让你的抓取行为和用户访问网站的真实行为尽量一致 1.伪造UA字符串,每次请求都使用随机生成的UA 为了减少复杂度,随机生成UA的功能通过第三方模块库fake-userag ...