信息学奥赛一本通 1384:珍珠(bead)

Posted 君义_noip

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了信息学奥赛一本通 1384:珍珠(bead)相关的知识,希望对你有一定的参考价值。

【题目链接】

ybt 1384:珍珠(bead)

【题目考点】

1. 图论:floyd 求传递闭包

传递闭包:二维数组e,e[i][j]表示顶点i到顶点j是否有路径。

【解题思路】

这是个有向图。每颗珍珠是一个顶点,初始情况下,如果i比j重,那么i到j有一条弧。
设布尔类型数组e,为该图的传递闭包,即e[i][j]表示i是否比j重。
先输入已知的相对重量关系,如果输入了x,y,那么x比y重,将e[x][y]设为1。
而后在e数组上使用floyd算法求传递闭包。k, i, j三重循环,如果i到j的重量关系还没确定(e[i][j]==0),但是i比k重,k比j重,那么一定有i比j重。
e[i][0]记录比i轻的珍珠的数量,e[0][j]记录比j重的珍珠的数量。遍历传递闭包e,如果e[i][j]为真,即i比j重,那么比i轻的珍珠的数量增加1,比j重的珍珠数量增加1。
已知n是奇数,那么n/2(n整除2)的结果等于(n-1)/2。

  • 如果比i重的珍珠数量大于n/2,超过了一半,那么i的重量一定不是中间重量
  • 如果比i轻的珍珠数量大于n/2,超过了一半,那么i的重量也一定不是中间重量

统计不可能是中间重量的珍珠的数量,输出结果。

【题解代码】

解法1:floyd求传递闭包

#include<bits/stdc++.h>
using namespace std;
#define N 105
int n, m, e[N][N], ct;//n:顶点数 m:边数 e[i][j]:输入数据中i比j重 
int main()

	int x, y;
	cin >> n >> m;
	for(int i = 1; i <= m; ++i)
	
		cin >> x >> y;
		e[x][y] = 1;
	
	for(int k = 1; k <= n; ++k)
		for(int i = 1; i <= n; ++i)
			for(int j = 1; j <= n; ++j)
				if(e[i][j] == 0 && e[i][k] && e[k][j])
					e[i][j] = 1;
	for(int i = 1; i <= n; ++i)
		for(int j = 1; j <= n; ++j)
			if(e[i][j])
			
				e[i][0]++;//e[i][0]:比i轻的数量 
				e[0][j]++;//e[0][j]:比j重的数量
			
	for(int i = 1; i <= n; ++i)
		if(e[i][0] > n/2 || e[0][i] > n/2)
			ct++;
	cout << ct;
	return 0;

[信息学奥赛一本通oj1741]电子速度 题解

技术图片

 

 

 

对于$100 \\%$的数据,$1≤n,m≤1e6 0<=x_i,y_i<20170927 1≤l_i,r_i≤n $

 

 

 

$Solution:$

一开始没看懂题。后来大致理解了一下,所谓的v是一个二维向量,有x和y两个参数。那个$ imes$是叉乘,即$(x_i y_j-x_j y_i)$。

所以题意就是给你一个x序列和y序列,对于每次询问的区间$[l,r]$,求$sum limits _{lleq i<j leq r}(x_iy_j-x_jy_i)^2$。带修。

点对的形式比较麻烦,尝试化成单点的柿子:

先拆平方:

$sum limits _{lleq i<j leq r}x_i^2y_j^2-2x_ix_jy_iy_j+x_j^2y_i^2$

遍历每个点对就相当与计入每个点的贡献。所以:

$sum limits_{i=l}^r x_i^2 sum limits _{i=l}^r y_i^2- (sum limits_{i=l}^r x_iy_i)^2$

然后开三个树状数组分别维护${x_i}^2,{y_i}^2,x_i y_i$即可。

 

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
#define pa pair<ll,ll>
typedef long long ll;
const ll mod=20170927;
ll read()
{
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)){if(ch==‘-‘)f=-1;ch=getchar();}
    while(isdigit(ch))x=x*10+ch-‘0‘,ch=getchar();
    return x*f;
}
const int N=1e6+5;
int n,m;
ll c[3][N];
pa v[N];
int lb(int x){return x&-x;}
void add(int x,ll val,int id)
{
    for( ;x<=n;x+=lb(x))
        c[id][x]+=val,(c[id][x]+=mod)%=mod;
}
ll query(int x,int id)
{
    ll res=0;
    for( ;x;x-=lb(x))
        (res+=c[id][x])%=mod;
    return (res+mod)%mod;
}
ll ask(int l,int r,int id)
{
    return (query(r,id)-query(l-1,id)+mod)%mod;
}
int main()
{
    n=read();m=read();
    for(int i=1;i<=n;i++)
    {
        v[i].first=read(),v[i].second=read();
        add(i,v[i].first*v[i].first,0);
        add(i,v[i].second*v[i].second,1);
        add(i,v[i].first*v[i].second,2);
    }

    while(m--)
    {
        int op=read();
        if(op==1)
        {
            int pos=read();
            ll x=read(),y=read();
            add(pos,x*x-v[pos].first*v[pos].first,0);
            add(pos,y*y-v[pos].second*v[pos].second,1);
            add(pos,x*y-v[pos].first*v[pos].second,2);
            v[pos].first=x;v[pos].second=y;

        }
        if(op==2)
        {
            int l=read(),r=read();
            ll res=ask(l,r,0)*ask(l,r,1)%mod,res1=ask(l,r,2);
            res=(res-(res1*res1%mod)+mod)%mod;
            printf("%lld
",res);
        }
    }
    return 0;
}

 

以上是关于信息学奥赛一本通 1384:珍珠(bead)的主要内容,如果未能解决你的问题,请参考以下文章

信息学奥赛一本通为啥不通过

长春市哪里有卖这本信息学奥赛一本通c++的书店?

信息奥赛一本通 1060:均值

信息学奥赛一本通Part1.2 基础算法-二分与三分

一道信息学奥赛NOIP提高组难度的题

《信息学奥赛一本通》 高精度加法。输入两个正整数,求它们的和。