B.
题目链接:https://hihocoder.com/problemset/problem/1509
题意:给定一个长度为 n 的非负整数序列 a[1..n]
你需要求有多少个非负整数 S 满足以下两个条件:
(1).0 ≤ S < 260
(2).对于所有 1 ≤ i < n ,有 (a[i] xor S) ≤ (a[i+1] xor S)
思路:遍历每一对,找每一对第一个不相同的位,想要让前面的大于后面的则需要这样考虑:
1.如果a[i] 这位是1 , a[i+1] 这位是0,那么s这位必须为1
2.如果a[i] 这位是0 , a[i+1]这位是1,那么s这位必须是0
不满足条件就输出0,总共有60位,除了限定的位外,其他的都有2种情况,快速幂计算即可。
Code:
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#define LL long long
using namespace std;
const int AX = 1e5+66;
LL s[AX];
LL a[AX];
LL quick( LL a , LL b ){
LL ans = 1LL;
while( b ){
if( b & 1 ){
ans *= a;
}
b >>= 1 ;
a *= a ;
}
return ans ;
}
int main(){
int n;
LL res = 1LL ;
scanf("%d",&n);
for( int i = 0 ; i < n ; i++ ){
scanf("%lld",&a[i]);
}
int bit;
for( int i = 0 ; i < 60 ; i++ ) s[i] = -1;
for( int i = 0 ; i < n - 1 ; i++ ){
for( int j = 59 ; j >= 0 ; j-- ){
if( (1LL<<j) & ( a[i] ^ a[i+1] ) ){
if( a[i] & (1LL<<j) ){
if( s[j] == -1 ) s[j] = 1;
if( !s[j] ){ return 0*printf("0\n"); }
}else{
if( s[j] == -1 ) s[j] = 0;
if( s[j] ){ return 0*printf("0\n"); }
}
break;
}
}
}
int ans = 0 ;
for( int i = 0 ; i < 60 ; i++ ){
if( s[i] == -1 ) ans ++;
}
printf("%lld\n",quick(2,ans));
return 0 ;
}
C
题意:给出事件,要求实时输出1队的名次。
思路:如果输入的不是1队的事件,需要判断原来名次是否高于1队,如果高于1队,就删除原来的更新。如果小于1队并且现在的大于1队,直接插入。
如果是1队,就清除set里面名次低于1队的。最后容器的尺寸就是比1队名次高的
Code:
#include <bits/stdc++.h>
using namespace std;
const int AX = 1e5+66;
int n , m ;
struct Node{
int num ;
int p ;
Node( ){
num = 0 ;
p = 0 ;
}
}a[AX];
struct cmp{
bool operator()( const Node &a , const Node &b ) const{
return ( ( a.num == b.num && a.p > b.p ) || a.num < b.num );
}
};
multiset<Node,cmp>s ;
bool operator < ( Node x , Node y ){ return ( x.num == y.num && x.p > y.p ) || ( x.num < y.num ) ;}
bool operator > ( Node x , Node y ){ return ( x.num == y.num && x.p < y.p ) || ( x.num > y.num ) ;}
bool operator <= ( Node x , Node y ){ return !( y < x ) ;}
int main(){
int x , y ;
scanf("%d%d",&n,&m);
while( m -- ){
scanf("%d%d",&x,&y);
Node tmp = a[x];
a[x].num ++ ;
a[x].p += y ;
if( x == 1 ){
while( s.size() && (*s.begin()) <= a[1] ){
s.erase(s.begin());
}
}else{
if( a[1] < tmp ){
s.erase(s.find(tmp));
s.insert(a[x]);
}else if( a[1] < a[x] ) s.insert(a[x]);
}
printf("%d\n",s.size()+1);
}
return 0 ;
}
D
题意:给一个序列,要求构造一棵树,每次去掉最小的叶子和所连的边,序列是跟叶子相连的点。
思路:set维护下叶子序列,如果去掉一个叶子节点使得序列中的节点为叶子,就加入。
Code:
#include <iostream>
#include <cstdio>
#include <string>
#include <set>
#include <map>
#include <sstream>
using namespace std;
const int AX = 7500+66;
int a[AX];
map<int,int>mp;
set<int>s[AX];
set<int> leaf ;
int main(){
int n = 0 ;
string tmp ;
//while( ~scanf("%d",&a[n++]) );
getline(cin,tmp);
stringstream ss(tmp);
int nx = 0 ;
while( ss ){
ss >> a[n++];
if( nx < a[n-1] ) nx = a[n-1];
}
n -- ;
for( int i = 0 ; i < n ; i++ ){
mp[a[i]]++ ;
}
for( int i = 1 ; i <= nx ; i++ ){
if( !mp[i] ){
leaf.insert(i);
}
}
for( int i = 0 ; i < n ; i++ ){
mp[a[i]] -- ;
if( leaf.size() ){
s[a[i]].insert(*(leaf.begin()));
s[*(leaf.begin())].insert(a[i]);
leaf.erase(leaf.begin());
}
if( !mp[a[i]] ) leaf.insert(a[i]);
}
for( int i = 1 ; i <= nx ; i++ ){
printf("%d:",i);
int m = s[i].size();
set<int>::iterator it = s[i].begin();
for( ; it != s[i].end(); it++ ){
printf(" %d",(*it));
}printf("\n");
}
return 0 ;
}
G
题目链接:https://cn.vjudge.net/problem/FZU-2300
题意:
分别给定2个矩形的一个坐标以及长和宽,计算交的面积/并的面积。
思路:计算机和求交的面积,然后长乘宽算出总的面积-相交的就是并的。
那么只需要计算交的面积,首先确定两个矩形对角的点,通过交换构成下面的局面:
那么面积显而易见
Code:
#include <bits/stdc++.h>
#include <cstdio>
#include <algorithm>
const int AX = 1e5+66;
using namespace std;
#define swap(a,b) {double t;t=a;a=b;b=t;}
int main(){
double x , y , w , h;
double x1 , x2 ,x3 ,x4 ,x5 ,x6 ,x7 ,x8;
double y1 ,y2 ,y3 , y4 , y5 , y6 , y7 , y8;
int T;
scanf("%d",&T);
while( T-- ){
double xx[5], yy[5];
scanf("%lf%lf%lf%lf",&x,&y,&w,&h);
double re1 = w * h ;
x1 = x; y1 = y;
x2 = x; y2 = y + h ;
x3 = x + w ; y3 = y + h;
x4 = x + w ; y4 = y;
xx[0] = x2; yy[0] = y2;
xx[1] = x4; yy[1] = y4;
scanf("%lf%lf%lf%lf",&x,&y,&w,&h);
double re2 = w * h ;
x5 = x; y5 = y ;
x6 = x; y6 = y + h ;
x7 = x + w ; y7 = y + h ;
x8 = x + w ; y8 = y ;
xx[2] = x6 ; yy[2] = y6;
xx[3] = x8 ; yy[3] = y8;
if (xx[0] > xx[1])
swap(xx[0], xx[1]);
if (xx[2] > xx[3])
swap(xx[2], xx[3]);
if (yy[0] > yy[1])
swap(yy[0], yy[1]);
if (yy[2] > yy[3])
swap(yy[2], yy[3]);
if (xx[1] <= xx[2] || xx[0] >= xx[3] || yy[0] >= yy[3] || yy[1] <= yy[2]) {
printf("0.00\n");
continue;
}
else {
sort(xx, xx + 4);
sort(yy, yy + 4);
double sum = re1 + re2 ;
double jiao = (xx[2] - xx[1]) * (yy[2] - yy[1]);
double uni = sum - jiao;
printf("%.2lf\n", jiao / uni );
}
}
return 0 ;
}
H. 题目链接:https://cn.vjudge.net/problem/FZU-2294
思路:模拟题,注意开unsigned long long
Code:
#include <iostream>
#include <cstdio>
#include <map>
#include <string.h>
using namespace std;
const int AX = 1e5+66;
const unsigned long long INF = 140737488355328ULL;
map<int,string>mp1;
map<string,int>mp;
map<int,unsigned long long>val;
int tot ;
int main(){
ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0);
char op[50];
string a,b;
unsigned long long v;
tot = 0 ;
while( cin >> op ){
cin >> a;
if( !strcmp(op,"def") ){
cin >> v;
if( !mp[a] ){
mp[a] = ++tot;
mp1[tot] = a;
}
val[tot] = v;
cout << a << " = " << val[tot] << endl;
}else if( !strcmp(op,"add") ){
cin >> b;
val[mp[a]] += val[mp[b]];
val[mp[a]] %= INF;
cout << mp1[mp[a]] << " = " << val[mp[a]] << endl;
}else if( !strcmp(op,"sub") ){
cin >> b;
val[mp[a]] -= val[mp[b]];
val[mp[a]] = ( val[mp[a]] + INF ) % INF;
cout << mp1[mp[a]] << " = " << val[mp[a]] << endl;
}else if( !strcmp(op,"div") ){
cin >> b ;
val[mp[a]] /= val[mp[b]];
cout << mp1[mp[a]] << " = " << val[mp[a]] << endl;
}else if( !strcmp(op,"mul") ) {
cin >> b ;
val[mp[a]] = ( val[mp[a]] * val[mp[b]] ) % INF;
cout << mp1[mp[a]] << " = " << val[mp[a]] << endl;
}else{
cin >> b ;
val[mp[a]] %= val[mp[b]];
cout << mp1[mp[a]] << " = " << val[mp[a]] << endl;
}
}
return 0 ;
}
I
Code:
#include <iostream>
#include <cstdio>
#define LL long long
using namespace std;
const LL MOD = 1e9 + 7 ;
const int AX = 1e6+2;
LL inv[AX];
void init(){
inv[1] = 1;
for( int i = 2 ; i < AX ; i++ ){
inv[i] = (LL) ( MOD - MOD / i ) * inv[MOD%i] % MOD;
}
}
int main(){
ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);
int T;
cin >> T;
LL n , m ;
init();
while( T-- ){
cin >> n >> m ;
if( n < m ){
cout << n << endl;
}else{
//printf("%lld\n",((LL)((n+1)*m)%MOD*quick(m+1,MOD-2)%MOD)%MOD);
cout << (n+1)*m%MOD*inv[m+1]%MOD << endl;
}
}
return 0 ;
}
J
题意:给m个数,剩下的是important数,如果unimportant数是两个不同important数的最近公共祖先,那么这也是important数,求important数的数量。
思路:对于给定的数搜其子节点,1标记为unimp数,0标记为imp数,2标记为有一个imp节点为其祖先。
Code:
#include <bits/stdc++.h>
using namespace std;
const int AX = 1e5+66;
int tot ;
int head[AX<<1];
bool vis[AX];
int mark[AX];
int a[AX];
int f[AX];
struct Node{
int v , next;
}G[AX<<1];
void init(){
tot = 0 ;
memset( G , 0 , sizeof(G) ) ;
memset( head , -1 , sizeof(head) );
memset( f , -1 , sizeof(f) );
memset( vis , false , sizeof(vis) );
memset( mark , 0 , sizeof(mark));
}
void addEdege( int u , int v ){
G[tot].v = v ;
G[tot].next = head[u]; head[u] = tot++;
}
void build( int x , int pre ){
for( int i = head[x] ; ~i ; i = G[i].next ){
int v = G[i].v ;
if( v == pre ) continue;
f[v] = x;
build( v , x );
}
}
void dfs( int x ){
vis[x] = true ;
for( int i = head[x] ; ~i ; i = G[i].next ){
int v = G[i].v ;
if( v == f[x] ) continue;
if( mark[v] == 1 && !vis[v] ) dfs(v);
if( mark[v] == 2 || !mark[v] ){
if( mark[x] == 1 ) mark[x] = 2 ;
else {
mark[x] = 0 ; break ;
}
}
}
}
int main(){
int T;
scanf("%d",&T);
int n , q , m ;
int Case = 0 ;
int x , y ;
while( T-- ){
init();
scanf("%d%d",&n,&q);
for( int i = 1 ; i < n ; i++ ){
scanf("%d%d",&x,&y);
addEdege(x,y);
addEdege(y,x);
}
build( 1 , -1 );
int res ;
printf("Case #%d:\n",++Case);
while( q -- ) {
scanf("%d",&m);
res = n - m ;
for( int i = 0 ; i < m ; i++ ) {
scanf("%d",&a[i]);
mark[a[i]] = 1 ;
}
for( int i = 0 ; i < m ; i++ ){
if( !vis[a[i]] ){
dfs( a[i] );
}
}
for( int i = 0 ; i < m ; i++ ){
if( !mark[a[i]] ) res ++ ;
mark[a[i]] = 0 ;
vis[a[i]] = 0 ;
}
printf("%d\n",res);
}
}
return 0 ;
}
K 题目链接:https://cn.vjudge.net/problem/FZU-2298
题意:求s到t最短路,中间会等红绿灯。。。
思路:spfa求最短路,松弛操作的时候加个等红绿灯的时间就行了。多组输入记得清空。。因为这个好多题都wa1.
Code:
#include <iostream>
#include <cstdio>
#include <queue>
#include <vector>
#include <cstring>
#define INF 0x3f3f3f3f
using namespace std;
const int AX = 1e3+6;
int n , m ;
int a[AX];
std::vector<int> G[AX];
std::vector<int> W[AX];
int vis[AX];
long long dis[AX];
int cal( int x , int to ){
if( !x || !a[to] || x < a[to] ) return 0 ;
if( x % a[to] == 0 && ( x / a[to] ) % 2 == 0 ) return 0 ;
if( x % a[to] == 0 && ( x / a[to] ) % 2 == 1 ) return a[to] ;
if( ( x / a[to] ) % 2 == 0 ){
return 0 ;
}else{
int tmp = a[to];
while( tmp < x ){
tmp *= 2 ;
}
return tmp - x ;
}
}
void SPFA( int v0 ){
for( int i = 1 ; i <= n ; i++ ){
dis[i] = INF;
}
memset( vis , 0 , sizeof(vis) );
dis[v0] = 0 ;
queue<int>q;
q.push(v0);
vis[v0] = 1 ;
while( !q.empty() ){
int u = q.front();
q.pop();
vis[u] = 0;
for( int i = 0 ; i < G[u].size() ; i++ ){
int time = cal(dis[u],u);
if( dis[u] + W[u][i] + time < dis[G[u][i]] ){
dis[G[u][i]] = dis[u] + W[u][i] + time;
if( !vis[G[u][i]] ){
q.push(G[u][i]);
vis[G[u][i]] = 1;
}
}
}
}
}
int main(){
int T;
scanf("%d",&T);
while( T-- ){
scanf("%d%d",&n,&m);
for( int i = 1 ; i <= n ; i++ ){
scanf("%d",&a[i]);
}
for(int i = 0 ; i <= n ; i++ ) G[i].clear();
for(int i = 0 ; i <= n ; i++ ) W[i].clear();
int x , y , w;
while( m-- ){
scanf("%d%d%d",&x,&y,&w);
G[x].push_back(y);
G[y].push_back(x);
W[x].push_back(w);
W[y].push_back(w);
}
int s , t ;
scanf("%d%d",&s,&t);
SPFA(s);
printf("%d\n",dis[t]);
}
return 0 ;
}