版权声明:本文为博主原创文章,未经博主允许也可以转载。 https://blog.csdn.net/FrankAx/article/details/82561862
F
题意:给n个框架,每个给k个坐标,问最长的连续出现的坐标值长度。
思路:map直接记录就行了,只不过需要注意的是同一个框架会出现相同坐标。
Code:
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define LL long long
using namespace std;
typedef pair<int,int>P;
map<P, int> mp ;
map<P, int> num ;
int main(){
int T;
scanf("%d",&T);
while( T-- ){
int k ;
mp.clear();
num.clear();
int n ;
scanf("%d",&n);
int x , y ;
int res = 0 ;
for( int i = 1 ; i <= n ; i++ ){
scanf("%d",&k);
for( int j = 0 ; j < k ; j++ ){
scanf("%d%d",&x,&y);
if( mp[(P(x,y))] == i ) continue;
if( mp[P(x,y)] == i - 1 ){
num[P(x,y)] ++ ;
res = max( res , num[P(x,y)] ) ;
}else{
num[P(x,y)] = 1 ;
}
mp[P(x,y)] = i ;
}
}
printf("%d\n",res);
}
return 0 ;
}
H
题意:阅读L,R区间内的书可以获得知识量:
a[L] * ( R - L + 1 ) + a[L+1] * ( R - L ) ….. + a[R] * 1
给两个操作1 , L ,R ,查询看L,R页的书能够获得多少知识
2 , L , R : 将L位置的值更改为R
思路:两个树状数组,一个维护长度为n-i+1,以i为左边界,n右边界的知识和。
一个维护前缀和。
当查询L,R内的知识量时,首先用第一个树状数组求出的是a[L]* ( n - L + 1 ) + …+a[R] * ( n - R + 1 ) , 第二个树状数组求出的是 a[L] + ….+ a[R] ,
但是我们需要查询a[L] * ( R - L + 1 ) + a[L+1] * ( R - L ) ….. + a[R] * 1
可以看出中间相差 n - R
那么结果就是:第一个树状数组的结果 - ( n - r ) * 第二个树状数组的结果。
更新时,需要查询l位置原来的值tmp,然后加上r-tmp更新之。
Code:
#include <bits/stdc++.h>
#define LL unsigned long long
using namespace std ;
const int AX = 1e5+66;
LL c[AX];
LL c1[AX];
int lowbit( int x ) {
return x & (-x) ;
}
void update( int site , LL val ){
while( site < AX ){
c[site] += val ;
site += lowbit(site) ;
}
}
LL query( int site ){
LL ans = 0ULL ;
while( site > 0 ){
ans += c[site];
site -= lowbit(site);
}
return ans ;
}
void update1( int site , LL val ){
while( site < AX ){
c1[site] += val ;
site += lowbit(site) ;
}
}
LL query1( int site ){
LL ans = 0ULL ;
while( site > 0 ){
ans += c1[site];
site -= lowbit(site);
}
return ans ;
}
int main(){
int n , q ;
LL x ;
scanf("%d%d",&n,&q);
for( int i = 1 ; i <= n ; i++ ){
scanf("%lld",&x);
update( i , 1ULL * ( n - i + 1 ) * x );
update1( i , x ) ;
}
int op ;
int l , r ;
while( q-- ){
scanf("%d%d%d",&op,&l,&r);
if( op == 1 ){
LL ans = query( r ) - query( l - 1 ) ;
LL ans1 = 1ULL * ( n - r ) * ( query1( r ) - query1( l - 1 ) ) ;
printf("%lld\n",ans - ans1);
}else{
LL tmp = query1( l ) - query1( l - 1 ) ;
update( l , 1ULL * ( r - tmp ) * ( n - l + 1 ) ) ;
update1( l , 1ULL * ( r - tmp ) ) ;
}
}
return 0 ;
}
思路:既然迷宫花费最小,那么任意两点可到达,就是最大生成树。然后转化为树上任意两点之间的距离,用LCA处理,这里用的是离线的Tanjan算法。
Code:
#include <bits/stdc++.h>
#define LL long long
using namespace std;
const int AX = 1e6+666;
const int MAXN = 1e6;
struct Node{
int u ;
int v ;
int w ;
bool operator < ( const Node &a ) const{
return a.w < w;
}
}e[AX];
int n , m ;
int tot ;
int pre[AX];
int fa[AX];
int vis[AX];
int ans[AX];
int dis[AX];
struct node{
int to , w;
node( int a , int b ){
to = a; w = b ;
}
};
std::vector<int> vec[AX];
std::vector<node> Q[AX];
void addedge( int u , int v , int w ) {
e[tot].u = u ; e[tot].v = v ; e[tot++].w = w;
}
void init(){
memset( ans , 0, sizeof(ans) ) ;
memset( dis , 0 , sizeof(dis) ) ;
memset( vis , 0 , sizeof(vis) ) ;
for( int i = 1 ; i <= MAXN ; i++ ){
pre[i] = i ;
fa[i] = i ;
vec[i].clear();
Q[i].clear();
}
}
int find( int x ){
return x == pre[x] ? pre[x] : pre[x] = find(pre[x]);
}
void mix( int x , int y ){
int xx = find(x) ;
int yy = find(y) ;
if( xx != yy ){
pre[yy] = xx ;
}
}
void Kruscal(){
sort( e , e + tot );
for( int i = 0 ; i < tot ; i++ ){
if( find(e[i].u) != find(e[i].v) ){
mix( e[i].u , e[i].v ) ;
vec[e[i].u].push_back(e[i].v);
vec[e[i].v].push_back(e[i].u);
}
}
}
int find_fa( int x ){
return x == fa[x] ? fa[x] : fa[x] = find_fa( fa[x] ) ;
}
void Tarjan( int x , int f ){
fa[x] = x ;
vis[x] = 1 ;
for( int i = 0 ; i < vec[x].size() ; i++ ){
if( vec[x][i] == f ) continue;
int v = vec[x][i] ;
dis[v] = dis[x] + 1 ;
Tarjan( v , x );
}
for( int i = 0 ; i < Q[x].size() ; i++ ){
int v = Q[x][i].to;
if(vis[v]){
ans[Q[x][i].w]= dis[x] + dis[v] - 2 * dis[find_fa(v)] ;
}
}
fa[x] = f ;
}
int main(){
scanf("%d%d",&n,&m);
char op[5];
int d , r ;
tot = 0 ;
init();
for( int i = 0 ; i < n ; i++ ){
for( int j = 0 ; j < m ; j++ ){
scanf("%s%d%s%d",op,&d,op,&r);
int id = i * m + j + 1 ;
if( i < n ){
addedge( id , ( i + 1 ) * m + j + 1 , d );
}
if( j < m ){
addedge( id , id + 1 , r );
}
}
}
Kruscal();
int q;
scanf("%d",&q);
int x1 , x2 , y1 , y2 ;
for( int i = 1 ; i <= q ; i++ ){
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
x1-- ; x2--;
int id1 = x1 * m + y1 ;
int id2 = x2 * m + y2 ;
Q[id1].push_back(node(id2,i));
Q[id2].push_back(node(id1,i));
}
dis[1] = 0 ;
vis[1] = 1 ;
Tarjan(1,0);
for( int i = 1 ; i <= q ; i++ ){
printf("%d\n",ans[i]);
}
return 0 ;
}